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

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

Two modifications:
1/ fixing a bug in the DCACHE_CC_INVAL state, related
to the TLB invalidation procedure (the nline was not properly defined).
2/ simplifiing the DCACHE_DIRTY_SC_WAIT state behaviour, as suggested by Hao:
we still wait for the SC response, but we just return to IDLE state
without analysing the response (no difference between success of failure,
because the work is done by the coherence transaction...)

File size: 189.3 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, the page table must be updated
2966    {
2967        paddr_t   nline = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);   
2968        uint32_t  pte   = r_dcache_tlb_pte_flags.read();
2969        bool      updt  = false;
2970        bool      local = true;
2971
2972        // We should compute the access locality:
2973        // The PPN MSB bits define the destination cluster index.
2974        // The m_srcid_d MSB bits define the source cluster index.
2975        // The number of bits to compare depends on the number of clusters,
2976        // and can be obtained in the mapping table.
2977        // As long as this computation is not done, all access are local.
2978
2979        if ( local )                                            // local access
2980        {
2981            if ( not ((pte & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
2982            {
2983                updt                = true;
2984                r_dcache_vci_sc_old = pte;
2985                r_dcache_vci_sc_new = pte | PTE_L_MASK;
2986                pte                 = pte | PTE_L_MASK;
2987                r_dcache_tlb_pte_flags = pte;
2988            }
2989        }
2990        else                                                    // remote access
2991        {
2992            if ( not ((pte & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
2993            {
2994                updt                = true;
2995                r_dcache_vci_sc_old = pte;
2996                r_dcache_vci_sc_new = pte | PTE_R_MASK;
2997                pte                 = pte | PTE_R_MASK;
2998                r_dcache_tlb_pte_flags = pte;
2999            }
3000        }
3001
3002        // update TLB
3003        if ( r_dcache_tlb_ins.read() ) 
3004        {
3005            r_itlb.write( true,         // 2M page
3006                          pte,
3007                          0,            // argument unused for a PTE1
3008                          r_dcache_tlb_vaddr.read(),   
3009                          r_dcache_tlb_way.read(), 
3010                          r_dcache_tlb_set.read(),
3011                          nline );
3012#ifdef INSTRUMENTATION
3013m_cpt_itlb_write++;
3014#endif
3015        }
3016        else
3017        {
3018            r_dtlb.write( true,         // 2M page
3019                          pte,
3020                          0,            // argument unused for a PTE1
3021                          r_dcache_tlb_vaddr.read(),   
3022                          r_dcache_tlb_way.read(), 
3023                          r_dcache_tlb_set.read(),
3024                          nline );
3025#ifdef INSTRUMENTATION
3026m_cpt_dtlb_write++;
3027#endif
3028        }
3029        // next state
3030        if ( updt ) r_dcache_fsm = DCACHE_TLB_LR_UPDT;  // dcache and page table update
3031        else        r_dcache_fsm = DCACHE_TLB_RETURN;   // exit sub-fsm
3032
3033#if DEBUG_DCACHE
3034if ( m_debug_dcache_fsm )
3035{
3036    if ( r_dcache_tlb_ins.read() ) 
3037    {
3038        std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE1_UPDT> write PTE1 in ITLB";
3039        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
3040                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
3041        r_itlb.printTrace();
3042    }
3043    else                           
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   
3051}
3052#endif
3053        break;
3054    }
3055    /////////////////////////
3056    case DCACHE_TLB_PTE2_GET:   // Try to get a PTE2 (64 bits) in the dcache
3057    {
3058        uint32_t        pte_flags;
3059        uint32_t        pte_ppn;
3060        size_t          way;
3061        size_t          set;
3062        size_t          word; 
3063 
3064        bool     hit = r_dcache.read( r_dcache_tlb_paddr.read(),
3065                                      &pte_flags,
3066                                      &pte_ppn,
3067                                      &way,
3068                                      &set,
3069                                      &word );
3070#ifdef INSTRUMENTATION
3071m_cpt_dcache_data_read++;
3072m_cpt_dcache_dir_read++;
3073#endif
3074        if ( hit )      // request hits in dcache
3075        {
3076            if ( not (pte_flags & PTE_V_MASK) ) // unmapped
3077            {
3078                if ( r_dcache_tlb_ins.read() ) 
3079                {
3080                    r_mmu_ietr             = MMU_READ_PT2_UNMAPPED;
3081                    r_mmu_ibvar            = r_dcache_tlb_vaddr.read();
3082                    r_icache_tlb_miss_req  = false;
3083                    r_icache_tlb_rsp_error = true;
3084                }
3085                else
3086                {
3087                    r_mmu_detr             = MMU_READ_PT2_UNMAPPED;
3088                    r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
3089                    m_drsp.valid             = true;
3090                    m_drsp.error             = true;
3091                }
3092                r_dcache_fsm          = DCACHE_IDLE;
3093
3094#if DEBUG_DCACHE
3095if ( m_debug_dcache_fsm )
3096{
3097    std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE2_GET> HIT in dcache, but PTE is unmapped"
3098              << " PTE_FLAGS = " << std::hex << pte_flags
3099              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3100}
3101#endif
3102            }
3103            else                                // mapped : we must update the TLB
3104            {
3105                r_dcache_in_tlb[m_dcache_sets*way+set] = true;
3106                r_dcache_tlb_pte_flags  = pte_flags;
3107                r_dcache_tlb_pte_ppn    = pte_ppn;
3108                r_dcache_tlb_cache_way  = way;
3109                r_dcache_tlb_cache_set  = set;
3110                r_dcache_tlb_cache_word = word;
3111                r_dcache_fsm            = DCACHE_TLB_PTE2_SELECT;
3112
3113#if DEBUG_DCACHE
3114if ( m_debug_dcache_fsm )
3115{
3116    std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE2_GET> HIT in dcache:"
3117              << " PTE_FLAGS = " << std::hex << pte_flags
3118              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3119}
3120#endif
3121             }
3122        }
3123        else            // we must load the missing cache line in dcache
3124        {
3125            r_dcache_fsm          = DCACHE_MISS_VICTIM; 
3126            r_dcache_vci_miss_req = true;
3127            r_dcache_vci_paddr    = r_dcache_tlb_paddr.read();
3128            r_dcache_miss_type    = PTE2_MISS;
3129
3130#if DEBUG_DCACHE
3131if ( m_debug_dcache_fsm )
3132{
3133    std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE2_GET> MISS in dcache:"
3134              << " PTE address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
3135}
3136#endif
3137        }
3138        break;
3139    }
3140    ////////////////////////////
3141    case DCACHE_TLB_PTE2_SELECT:    // select a slot for PTE2
3142    {
3143        size_t way;
3144        size_t set;
3145
3146        if ( r_dcache_tlb_ins.read() )
3147        {
3148            r_itlb.select( r_dcache_tlb_vaddr.read(),
3149                           false,       // PTE2
3150                           &way,
3151                           &set );
3152#ifdef INSTRUMENTATION
3153m_cpt_itlb_read++;
3154#endif
3155        }
3156        else
3157        {
3158            r_dtlb.select( r_dcache_tlb_vaddr.read(),
3159                           false,       // PTE2
3160                           &way,
3161                           &set );
3162#ifdef INSTRUMENTATION
3163m_cpt_dtlb_read++;
3164#endif
3165        }
3166
3167#if DEBUG_DCACHE
3168if ( m_debug_dcache_fsm )
3169{
3170    if ( r_dcache_tlb_ins.read() ) 
3171        std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE2_SELECT> Select a slot in ITLB:";
3172    else                           
3173        std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE2_SELECT> Select a slot in DTLB:";
3174        std::cout << " way = " << std::dec << way
3175                  << " / set = " << set << std::endl;
3176}
3177#endif
3178        r_dcache_tlb_way = way;
3179        r_dcache_tlb_set = set;
3180        r_dcache_fsm     = DCACHE_TLB_PTE2_UPDT;
3181        break;
3182    }
3183    //////////////////////////
3184    case DCACHE_TLB_PTE2_UPDT:          // write a new PTE2 in tlb after testing the L/R bit
3185                                        // if L/R bit already set, exit the sub-fsm
3186                                        // if not, the page table must be updated by an atomic access
3187    {
3188        paddr_t         nline     = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);   
3189        uint32_t        pte_flags = r_dcache_tlb_pte_flags.read();
3190        uint32_t        pte_ppn   = r_dcache_tlb_pte_ppn.read();
3191        bool            updt      = false;
3192        bool            local     = true;
3193
3194        // We should compute the access locality:
3195        // The PPN MSB bits define the destination cluster index.
3196        // The m_srcid_d MSB bits define the source cluster index.
3197        // The number of bits to compare depends on the number of clusters,
3198        // and can be obtained in the mapping table.
3199        // As long as this computation is not done, all access are local.
3200
3201        if ( local )                                            // local access
3202        {
3203            if ( not ((pte_flags & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
3204            {
3205                updt                = true;
3206                r_dcache_vci_sc_old = pte_flags;
3207                r_dcache_vci_sc_new = pte_flags | PTE_L_MASK;
3208                pte_flags           = pte_flags | PTE_L_MASK;
3209                r_dcache_tlb_pte_flags = pte_flags;
3210            }
3211        }
3212        else                                                    // remote access
3213        {
3214            if ( not ((pte_flags & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
3215            {
3216                updt                   = true;
3217                r_dcache_vci_sc_old = pte_flags;
3218                r_dcache_vci_sc_new = pte_flags | PTE_R_MASK;
3219                pte_flags           = pte_flags | PTE_R_MASK;
3220                r_dcache_tlb_pte_flags = pte_flags;
3221            }
3222        }
3223       
3224        // update TLB for a PTE2
3225        if ( r_dcache_tlb_ins.read() ) 
3226        {
3227            r_itlb.write( false,        // 4K page
3228                          pte_flags,
3229                          pte_ppn,
3230                          r_dcache_tlb_vaddr.read(),   
3231                          r_dcache_tlb_way.read(), 
3232                          r_dcache_tlb_set.read(),
3233                          nline );
3234#ifdef INSTRUMENTATION
3235m_cpt_itlb_write++;
3236#endif
3237        }
3238        else
3239        {
3240            r_dtlb.write( false,        // 4K page
3241                          pte_flags,
3242                          pte_ppn,
3243                          r_dcache_tlb_vaddr.read(),   
3244                          r_dcache_tlb_way.read(), 
3245                          r_dcache_tlb_set.read(),
3246                          nline );
3247#ifdef INSTRUMENTATION
3248m_cpt_dtlb_write++;
3249#endif
3250        }
3251
3252#if DEBUG_DCACHE
3253if ( m_debug_dcache_fsm )
3254{
3255    if ( r_dcache_tlb_ins.read() ) 
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    else                           
3263    {
3264        std::cout << "  <PROC " << name() << ".DCACHE_TLB_PTE2_UPDT> write PTE2 in DTLB";
3265        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
3266                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
3267        r_dtlb.printTrace();
3268    }
3269}
3270#endif
3271        // next state
3272        if ( updt ) r_dcache_fsm = DCACHE_TLB_LR_UPDT;  // dcache and page table update
3273        else        r_dcache_fsm = DCACHE_TLB_RETURN;   // exit sub-fsm
3274        break;
3275    }
3276    ////////////////////////
3277    case DCACHE_TLB_LR_UPDT:            // update the dcache after a tlb miss (L/R bit),
3278                                        // request a SC transaction to CMD FSM
3279    {
3280#if DEBUG_DCACHE
3281if ( m_debug_dcache_fsm )
3282{
3283    std::cout << "  <PROC " << name() << ".DCACHE_TLB_LR_UPDT> Update dcache: (L/R) bit" << std::endl;
3284}
3285#endif
3286        r_dcache.write(r_dcache_tlb_cache_way.read(),
3287                       r_dcache_tlb_cache_set.read(),
3288                       r_dcache_tlb_cache_word.read(),
3289                       r_dcache_tlb_pte_flags.read());
3290#ifdef INSTRUMENTATION
3291m_cpt_dcache_data_write++;
3292#endif
3293        // r_dcache_vci_sc_old & r_dcache_vci_sc_new registers are already set
3294        r_dcache_vci_paddr   = r_dcache_tlb_paddr.read();
3295        r_dcache_vci_sc_req  = true;
3296        r_dcache_fsm         = DCACHE_TLB_LR_WAIT;
3297        break;
3298    }
3299    ////////////////////////
3300    case DCACHE_TLB_LR_WAIT:            // Waiting the response to SC transaction.
3301                                    // We consume the response in rsp FIFO,
3302                                    // and exit the sub-fsm, but we don't
3303                                    // analyse the response, because we don't
3304                                    // care if the L/R bit update is not done.
3305                                    // We must take the coherence requests because
3306                                    // there is a risk of dead-lock
3307
3308    {
3309        // external coherence request
3310        if ( r_tgt_dcache_req )
3311        {
3312            r_dcache_fsm         = DCACHE_CC_CHECK;
3313            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3314            break;
3315        }
3316
3317        if ( r_vci_rsp_data_error.read() )      // bus error
3318        {
3319            std::cout << "BUS ERROR in DCACHE_TLB_LR_WAIT state" << std::endl;
3320            std::cout << "This should not happen in this state" << std::endl;
3321            exit(0);
3322        }
3323        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
3324        {
3325#if DEBUG_DCACHE
3326if ( m_debug_dcache_fsm )
3327{
3328    std::cout << "  <PROC " << name() << ".DCACHE_TLB_LR_WAIT> SC response received" << std::endl;
3329}
3330#endif
3331            vci_rsp_fifo_dcache_get = true;     
3332            r_dcache_fsm            = DCACHE_TLB_RETURN;
3333        }
3334        break;
3335    }
3336    ///////////////////////
3337    case DCACHE_TLB_RETURN:             // return to caller depending on tlb miss type
3338    {
3339#if DEBUG_DCACHE
3340if ( m_debug_dcache_fsm )
3341{
3342    std::cout << "  <PROC " << name() << ".DCACHE_TLB_RETURN> TLB MISS completed" << std::endl;
3343}
3344#endif
3345        if ( r_dcache_tlb_ins.read() ) r_icache_tlb_miss_req = false;
3346        r_dcache_fsm = DCACHE_IDLE;
3347        break;
3348    }
3349    ///////////////////////
3350    case DCACHE_XTN_SWITCH:             // Both itlb and dtlb must be flushed
3351    {
3352        if ( not r_dcache_xtn_req.read() )
3353        {
3354            r_dtlb.flush();
3355            r_dcache_fsm = DCACHE_IDLE;
3356            m_drsp.valid = true;
3357        }
3358        break;
3359    }
3360    /////////////////////
3361    case DCACHE_XTN_SYNC:               // waiting until write buffer empty
3362                                        // The coherence request must be taken
3363                                        // as there is a risk of dead-lock
3364    {
3365        // external coherence request
3366        if ( r_tgt_dcache_req.read() )   
3367        {
3368            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3369            r_dcache_fsm         = DCACHE_CC_CHECK;
3370        }       
3371
3372        if ( r_wbuf.empty() )
3373        {
3374            m_drsp.valid   = true;
3375            r_dcache_fsm = DCACHE_IDLE;
3376        }
3377        break;
3378    }
3379    ////////////////////////
3380    case DCACHE_XTN_IC_FLUSH:           // Waiting completion of an XTN request to the ICACHE FSM
3381    case DCACHE_XTN_IC_INVAL_VA:        // Caution : the itlb miss requests must be taken
3382    case DCACHE_XTN_IC_INVAL_PA:        // because the XTN_ICACHE_INVAL request to icache
3383    case DCACHE_XTN_IT_INVAL:           // can generate an itlb miss...
3384    {
3385        // external coherence request
3386        if ( r_tgt_dcache_req )   
3387        {
3388            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3389            r_dcache_fsm         = DCACHE_CC_CHECK;
3390            break;
3391        } 
3392
3393        // itlb miss request
3394        if ( r_icache_tlb_miss_req.read() )
3395        {
3396            r_dcache_tlb_ins    = true;
3397            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
3398            r_dcache_fsm        = DCACHE_TLB_MISS;
3399            break;
3400        }
3401
3402        // test if XTN request to icache completed
3403        if ( not r_dcache_xtn_req.read() ) 
3404        {
3405            r_dcache_fsm = DCACHE_IDLE;
3406            m_drsp.valid = true;
3407        }
3408        break;
3409    }
3410    /////////////////////////
3411    case DCACHE_XTN_DC_FLUSH:   // Invalidate sequencially all cache lines, using
3412                                // the r_dcache_flush counter as a slot counter.
3413                                // We loop in this state until all slots have been visited.
3414                                // A cleanup request is generated for each valid line
3415                                // and we are blocked until the previous cleanup is completed
3416                                // Finally, both the itlb and dtlb are flushed
3417                                // (including global entries)
3418    {
3419        if ( not r_dcache_cleanup_req )
3420        {
3421            paddr_t     nline;
3422            size_t      way = r_dcache_flush_count.read()/m_icache_sets;
3423            size_t      set = r_dcache_flush_count.read()%m_icache_sets;
3424
3425            bool        cleanup_req = r_dcache.inval( way,
3426                                                      set,
3427                                                      &nline );
3428            if ( cleanup_req ) 
3429            {
3430                r_dcache_cleanup_req  = true;
3431                r_dcache_cleanup_line = nline;
3432            }
3433
3434            r_dcache_in_tlb[m_dcache_sets*way+set]       = false;
3435            r_dcache_contains_ptd[m_dcache_sets*way+set] = false;
3436
3437            r_dcache_flush_count = r_dcache_flush_count.read() + 1;
3438
3439            if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) ) // last
3440            {
3441                r_dtlb.reset();   
3442                r_itlb.reset(); 
3443                r_dcache_fsm = DCACHE_IDLE;
3444                m_drsp.valid = true;
3445            }
3446        }
3447        break;
3448    }
3449    /////////////////////////
3450    case DCACHE_XTN_DT_INVAL:   // handling processor XTN_DTLB_INVAL request
3451    {
3452        r_dtlb.inval(r_dcache_p0_wdata.read());
3453        r_dcache_fsm        = DCACHE_IDLE;
3454        m_drsp.valid          = true;
3455        break;
3456    }
3457    ////////////////////////////
3458    case DCACHE_XTN_DC_INVAL_VA:  // selective cache line invalidate with virtual address
3459                                  // requires 3 cycles: access tlb, read cache, inval cache
3460                                  // we compute the physical address in this state
3461    {
3462        paddr_t paddr;
3463        bool    hit;
3464
3465        if ( r_mmu_mode.read() & DATA_TLB_MASK )        // dtlb activated
3466        {
3467#ifdef INSTRUMENTATION
3468m_cpt_dtlb_read++;
3469#endif
3470            hit = r_dtlb.translate( r_dcache_p0_wdata.read(),
3471                                    &paddr ); 
3472        }
3473        else                                            // dtlb not activated
3474        {
3475            paddr = (paddr_t)r_dcache_p0_wdata.read();
3476            hit   = true;
3477        }
3478
3479        if ( hit )              // tlb hit
3480        {
3481            r_dcache_p0_paddr = paddr;
3482            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_PA;
3483        }
3484        else                    // tlb miss
3485        {
3486#ifdef INSTRUMENTATION
3487m_cpt_dtlb_miss++;
3488#endif
3489            r_dcache_tlb_ins    = false;                // dtlb
3490            r_dcache_tlb_vaddr  = r_dcache_p0_wdata.read();
3491            r_dcache_fsm        = DCACHE_TLB_MISS; 
3492        } 
3493 
3494#if DEBUG_DCACHE
3495if ( m_debug_dcache_fsm )
3496{
3497    std::cout << "  <PROC " << name() << ".DCACHE_XTN_DC_INVAL_VA> Compute physical address" << std::hex
3498              << " / VADDR = " << r_dcache_p0_wdata.read()
3499              << " / PADDR = " << paddr << std::endl;
3500}
3501#endif
3502
3503        break;
3504    }
3505    ////////////////////////////
3506    case DCACHE_XTN_DC_INVAL_PA:  // selective cache line invalidate with physical address
3507                                  // requires 2 cycles: read cache / inval cache
3508                                  // In this state we read dcache.
3509    {
3510        uint32_t        data;
3511        size_t          way;
3512        size_t          set;
3513        size_t          word;
3514        bool            hit = r_dcache.read( r_dcache_p0_paddr.read(),
3515                                             &data,
3516                                             &way,
3517                                             &set,
3518                                             &word );
3519#ifdef INSTRUMENTATION
3520m_cpt_dcache_data_read++;
3521m_cpt_dcache_dir_read++;
3522#endif
3523        if ( hit )      // inval to be done
3524        {
3525            r_dcache_xtn_way = way;
3526            r_dcache_xtn_set = set;
3527            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_GO;
3528        }
3529        else            // miss : nothing to do
3530        {
3531            r_dcache_fsm      = DCACHE_IDLE;
3532            m_drsp.valid        = true;
3533        }
3534
3535#if DEBUG_DCACHE
3536if ( m_debug_dcache_fsm )
3537{
3538    std::cout << "  <PROC " << name() << ".DCACHE_XTN_DC_INVAL_PA> Test hit in dcache" << std::hex
3539              << " / PADDR = " << r_dcache_p0_paddr.read() << std::dec
3540              << " / HIT = " << hit
3541              << " / SET = " << set
3542              << " / WAY = " << way << std::endl;
3543}
3544#endif
3545        break;
3546    }
3547    ////////////////////////////
3548    case DCACHE_XTN_DC_INVAL_GO:  // In this state, we invalidate the cache line
3549                                              // Blocked if previous cleanup not completed
3550                                  // Test if itlb or dtlb inval is required   
3551    {
3552        if ( not r_dcache_cleanup_req.read() )
3553        {
3554            paddr_t     nline;
3555            size_t      way        = r_dcache_xtn_way.read();
3556            size_t      set        = r_dcache_xtn_set.read();
3557            bool    hit;
3558   
3559            hit = r_dcache.inval( way,
3560                                  set,
3561                                  &nline );
3562            assert(hit && "XTN_DC_INVAL way/set should still be in cache");
3563
3564            // request cleanup
3565            r_dcache_cleanup_req  = true;
3566            r_dcache_cleanup_line = nline;
3567           
3568            // possible itlb & dtlb invalidate
3569            if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
3570            {
3571                r_dcache_tlb_inval_line  = nline;
3572                r_dcache_tlb_inval_count = 0;
3573                r_dcache_fsm_scan_save   = DCACHE_XTN_DC_INVAL_END;
3574                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
3575                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3576            }
3577            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
3578            {
3579                r_itlb.reset();
3580                r_dtlb.reset();
3581                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
3582                r_dcache_fsm = DCACHE_IDLE;
3583                m_drsp.valid = true;
3584            }
3585            else
3586            {
3587                r_dcache_fsm = DCACHE_IDLE;
3588                m_drsp.valid = true;
3589            }
3590
3591#if DEBUG_DCACHE
3592if ( m_debug_dcache_fsm )
3593{
3594    std::cout << "  <PROC " << name() << ".DCACHE_XTN_DC_INVAL_GO> Actual dcache inval" << std::hex
3595              << " / NLINE = " << nline << std::endl;
3596}
3597#endif
3598        }
3599        break;
3600    }
3601    //////////////////////////////
3602    case DCACHE_XTN_DC_INVAL_END:       // send response to processor XTN request
3603    {
3604        r_dcache_fsm = DCACHE_IDLE;
3605        m_drsp.valid = true;
3606        break;
3607    }
3608    ////////////////////////
3609    case DCACHE_MISS_VICTIM:            // Selects a victim line if there is no pending cleanup
3610                                        // on the missing line, and if a new cleanup can be posted.
3611                                        // Set the r_dcache_cleanup_req flip-flop if required
3612    {
3613        size_t index;   // unused
3614        bool hit = r_cleanup_buffer.hit( r_dcache_vci_paddr.read()>>(uint32_log2(m_dcache_words)+2), &index );
3615        if ( not hit and not r_dcache_cleanup_req.read() )
3616        {
3617            bool      valid;
3618            size_t    way;
3619            size_t    set;
3620            paddr_t   victim;
3621
3622            valid = r_dcache.victim_select( r_dcache_vci_paddr.read(),
3623                                            &victim,
3624                                            &way,
3625                                            &set );
3626            r_dcache_miss_way = way;
3627            r_dcache_miss_set = set;
3628
3629            if ( valid )
3630            {
3631                r_dcache_cleanup_req  = true;
3632                r_dcache_cleanup_line = victim;
3633                r_dcache_fsm          = DCACHE_MISS_INVAL;
3634            }
3635            else
3636            {
3637                r_dcache_fsm          = DCACHE_MISS_WAIT;
3638            }
3639
3640#if DEBUG_DCACHE
3641if ( m_debug_dcache_fsm )
3642{
3643    std::cout << "  <PROC " << name() << ".DCACHE_MISS_VICTIM> Select a slot:" << std::dec
3644              << " / WAY = "   << way
3645              << " / SET = "   << set
3646              << " / VALID = "  << valid
3647              << " / LINE = " << std::hex << victim << std::endl; 
3648}
3649#endif
3650        }
3651        break;
3652    }
3653    ///////////////////////
3654    case DCACHE_MISS_INVAL:             // invalidate the victim line
3655                                        // and possibly request itlb or dtlb invalidate
3656    {
3657        paddr_t nline;
3658        size_t  way        = r_dcache_miss_way.read();
3659        size_t  set        = r_dcache_miss_set.read();
3660        bool    hit;
3661
3662        hit = r_dcache.inval( way, 
3663                        set,
3664                        &nline );
3665
3666        assert(hit && "selected way/set line should be in dcache");
3667
3668#if DEBUG_DCACHE
3669if ( m_debug_dcache_fsm )
3670{
3671    std::cout << "  <PROC " << name() << ".DCACHE_MISS_INVAL> inval line:" << std::dec
3672              << " / way = "   << way
3673              << " / set = "   << set
3674              << " / nline = "  << std::hex << nline << std::endl; 
3675}
3676#endif
3677        // if selective itlb & dtlb invalidate are required
3678        // the miss response is not handled before invalidate completed
3679        if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
3680        {
3681            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3682            r_dcache_tlb_inval_line  = nline;
3683            r_dcache_tlb_inval_count = 0;
3684            r_dcache_fsm_scan_save   = DCACHE_MISS_WAIT;
3685            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
3686        }
3687        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
3688        {
3689            r_itlb.reset();
3690            r_dtlb.reset();
3691            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
3692            r_dcache_fsm = DCACHE_MISS_WAIT;
3693        }
3694        else
3695        {
3696            r_dcache_fsm = DCACHE_MISS_WAIT;
3697        }
3698        break;
3699    }
3700    //////////////////////
3701    case DCACHE_MISS_WAIT:      // waiting the response to a miss request from VCI_RSP FSM
3702                                // This state is in charge of error signaling
3703                                // There is 5 types of error depending on the requester
3704    {
3705        // external coherence request
3706        if ( r_tgt_dcache_req ) 
3707        {
3708            r_dcache_fsm_cc_save = r_dcache_fsm;
3709            r_dcache_fsm         = DCACHE_CC_CHECK;
3710            break;
3711        }
3712
3713        if ( r_vci_rsp_data_error.read() )                      // bus error
3714        {
3715            switch ( r_dcache_miss_type.read() )
3716            {
3717                case PROC_MISS: 
3718                {
3719                    r_mmu_detr            = MMU_READ_DATA_ILLEGAL_ACCESS; 
3720                    r_mmu_dbvar           = r_dcache_p0_vaddr.read();
3721                    m_drsp.valid            = true;
3722                    m_drsp.error            = true;
3723                    r_dcache_fsm          = DCACHE_IDLE;
3724                    break;
3725                }
3726                case PTE1_MISS:
3727                {
3728                    if ( r_dcache_tlb_ins.read() )
3729                    {
3730                        r_mmu_ietr              = MMU_READ_PT1_ILLEGAL_ACCESS;
3731                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
3732                        r_icache_tlb_miss_req   = false;
3733                        r_icache_tlb_rsp_error  = true;
3734                    }
3735                    else
3736                    {
3737                        r_mmu_detr              = MMU_READ_PT1_ILLEGAL_ACCESS;
3738                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
3739                        m_drsp.valid              = true;
3740                        m_drsp.error              = true;
3741                    }
3742                    r_dcache_fsm                = DCACHE_IDLE;
3743                    break;
3744                }
3745                case PTE2_MISS: 
3746                {
3747                    if ( r_dcache_tlb_ins.read() )
3748                    {
3749                        r_mmu_ietr              = MMU_READ_PT2_ILLEGAL_ACCESS;
3750                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
3751                        r_icache_tlb_miss_req   = false;
3752                        r_icache_tlb_rsp_error  = true;
3753                    }
3754                    else
3755                    {
3756                        r_mmu_detr              = MMU_READ_PT2_ILLEGAL_ACCESS;
3757                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
3758                        m_drsp.valid              = true;
3759                        m_drsp.error              = true;
3760                    }
3761                    r_dcache_fsm                = DCACHE_IDLE;
3762                    break;
3763                }
3764            } // end switch type
3765            r_vci_rsp_data_error = false;
3766        }
3767        else if ( r_vci_rsp_fifo_dcache.rok() )         // valid response available
3768        {
3769            r_dcache_miss_word = 0;
3770            r_dcache_fsm       = DCACHE_MISS_UPDT;
3771        }       
3772        break;
3773    }
3774    //////////////////////
3775    case DCACHE_MISS_UPDT:      // update the dcache (one word per cycle)
3776                                // returns the response depending on the miss type
3777    {
3778        if ( r_vci_rsp_fifo_dcache.rok() )      // one word available
3779        {
3780            if ( r_dcache_miss_inval.read() )   // Matching coherence request
3781                                                // pop the FIFO, without cache update
3782                                                // send a cleanup for the missing line
3783                                                // if the previous cleanup is completed
3784            {
3785                if ( r_dcache_miss_word.read() < (m_dcache_words - 1) )     // not the last
3786                {
3787                    vci_rsp_fifo_dcache_get = true;
3788                    r_dcache_miss_word = r_dcache_miss_word.read() + 1;
3789                }
3790                else                                                    // last word
3791                {
3792                    if ( not r_dcache_cleanup_req.read() )      // no pending cleanup
3793                    {
3794                        vci_rsp_fifo_dcache_get = true;
3795                        r_dcache_cleanup_req    = true;
3796                        r_dcache_cleanup_line   = r_dcache_vci_paddr.read() >> 
3797                                                     (uint32_log2(m_dcache_words)+2);
3798                        r_dcache_miss_inval     = false;
3799                        r_dcache_fsm            = DCACHE_IDLE;
3800                    }
3801                }
3802            }
3803            else                                // No matching coherence request
3804                                                // pop the FIFO and update the cache
3805                                                // update the directory at the last word
3806            {
3807                 size_t way  = r_dcache_miss_way.read();
3808                 size_t set  = r_dcache_miss_set.read();
3809                 size_t word = r_dcache_miss_word.read();
3810
3811#ifdef INSTRUMENTATION
3812m_cpt_dcache_data_write++;
3813#endif
3814                r_dcache.write( way,
3815                                set,
3816                                word,
3817                                r_vci_rsp_fifo_dcache.read());
3818
3819                vci_rsp_fifo_dcache_get = true;
3820                r_dcache_miss_word = r_dcache_miss_word.read() + 1;
3821               
3822                // if last word, update directory, set in_tlb & contains_ptd bits
3823                if ( r_dcache_miss_word.read() == (m_dcache_words - 1) ) 
3824                {
3825
3826#ifdef INSTRUMENTATION
3827m_cpt_dcache_dir_write++;
3828#endif
3829                    r_dcache.victim_update_tag( r_dcache_vci_paddr.read(),
3830                                                r_dcache_miss_way.read(),
3831                                                r_dcache_miss_set.read() );
3832
3833                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3834                    r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
3835                   
3836                    if      (r_dcache_miss_type.read()==PTE1_MISS) r_dcache_fsm = DCACHE_TLB_PTE1_GET; 
3837                    else if (r_dcache_miss_type.read()==PTE2_MISS) r_dcache_fsm = DCACHE_TLB_PTE2_GET;
3838                    else                                           r_dcache_fsm = DCACHE_IDLE;
3839                }
3840            }
3841
3842#if DEBUG_DCACHE
3843if ( m_debug_dcache_fsm )
3844{
3845    if ( r_dcache_miss_inval.read() )
3846    {
3847        if ( r_dcache_miss_word.read() < m_dcache_words-1 ) 
3848        {
3849            std::cout << "  <PROC " << name() << ".DCACHE_MISS_UPDT> Matching coherence request:"
3850                      << "  pop the FIFO, don't update the cache" << std::endl;
3851        }
3852        else
3853        {
3854            std::cout << "  <PROC " << name() << ".DCACHE_MISS_UPDT> Matching coherence request:"
3855                      << " last word : send a cleanup request " << std::endl;
3856        }
3857    }
3858    else
3859    {
3860        std::cout << "  <PROC " << name() << ".DCACHE_MISS_UPDT> Write one word:"
3861                  << " address = " << std::hex << r_dcache_vci_paddr.read() 
3862                  << " / data = "  << r_vci_rsp_fifo_dcache.read()
3863                  << " / way = "   << std::dec << r_dcache_miss_way.read() 
3864                  << " / set = "   << r_dcache_miss_set.read()
3865                  << " / word = "  << r_dcache_miss_word.read() << std::endl; 
3866    }
3867}
3868#endif
3869 
3870        } // end if rok
3871        break;
3872    }
3873    /////////////////////
3874    case DCACHE_UNC_WAIT:
3875    {
3876        // external coherence request
3877        if ( r_tgt_dcache_req.read() ) 
3878        {
3879            r_dcache_fsm_cc_save = r_dcache_fsm;
3880            r_dcache_fsm         = DCACHE_CC_CHECK;
3881            break;
3882        }
3883
3884        if ( r_vci_rsp_data_error.read() )      // bus error
3885        {
3886            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
3887            r_mmu_dbvar          = m_dreq.addr;
3888            r_vci_rsp_data_error = false;
3889            m_drsp.error           = true;
3890            m_drsp.valid           = true;
3891            r_dcache_fsm         = DCACHE_IDLE;
3892            break;
3893        }
3894            else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
3895            {
3896            // consume data
3897            vci_rsp_fifo_dcache_get = true;     
3898            r_dcache_fsm            = DCACHE_IDLE;
3899
3900            // acknowledge the processor request if it has not been modified
3901            if ( m_dreq.valid and (m_dreq.addr == r_dcache_p0_vaddr.read()) )
3902            {
3903                    m_drsp.valid          = true;
3904                    m_drsp.rdata          = r_vci_rsp_fifo_dcache.read();
3905
3906                // makes reservation in case of LL
3907                if ( m_dreq.type == iss_t::DATA_LL )
3908                {
3909                    r_dcache_ll_valid = true;
3910                    r_dcache_ll_data  = r_vci_rsp_fifo_dcache.read();
3911                    r_dcache_ll_vaddr = m_dreq.addr;
3912                }
3913            }
3914            }   
3915        break;
3916    }
3917    ////////////////////
3918    case DCACHE_SC_WAIT:        // waiting VCI response after a processor SC request
3919    {
3920        // external coherence request
3921        if ( r_tgt_dcache_req.read() ) 
3922        {
3923            r_dcache_fsm_cc_save = r_dcache_fsm;
3924            r_dcache_fsm         = DCACHE_CC_CHECK;
3925            break;
3926        }
3927
3928        if ( r_vci_rsp_data_error.read() )              // bus error
3929        {
3930            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
3931            r_mmu_dbvar          = m_dreq.addr;
3932            r_vci_rsp_data_error = false;
3933            m_drsp.error         = true;
3934            m_drsp.valid         = true;
3935            r_dcache_fsm         = DCACHE_IDLE;
3936            break;
3937        }
3938        else if ( r_vci_rsp_fifo_dcache.rok() )         // response available
3939        {
3940            vci_rsp_fifo_dcache_get = true;     
3941            m_drsp.valid            = true;
3942            m_drsp.rdata            = r_vci_rsp_fifo_dcache.read();
3943            r_dcache_fsm            = DCACHE_IDLE;
3944        }       
3945        break;
3946    }
3947    //////////////////////////
3948    case DCACHE_DIRTY_GET_PTE:          // This sub_fsm set the PTE Dirty bit in memory
3949                                    // before handling a processor WRITE or SC request 
3950                                    // Input argument is r_dcache_dirty_paddr
3951                                    // In this first state, we get PTE value in dcache
3952                                    // and post a SC request to CMD FSM
3953    {
3954        // get PTE in dcache
3955        uint32_t pte;
3956        size_t   way;
3957        size_t   set;
3958        size_t   word;  // unused
3959        bool     hit = r_dcache.read( r_dcache_dirty_paddr.read(),
3960                                      &pte,
3961                                      &way,
3962                                      &set,
3963                                      &word );
3964#ifdef INSTRUMENTATION
3965m_cpt_dcache_data_read++;
3966m_cpt_dcache_dir_read++;
3967#endif
3968        assert( hit and "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
3969
3970        // request sc transaction to CMD_FSM
3971        r_dcache_dirty_way  = way; 
3972        r_dcache_dirty_set  = set; 
3973        r_dcache_vci_sc_req = true;
3974        r_dcache_vci_paddr  = r_dcache_dirty_paddr.read();
3975        r_dcache_vci_sc_old = pte;
3976        r_dcache_vci_sc_new = pte | PTE_D_MASK;
3977        r_dcache_fsm        = DCACHE_DIRTY_SC_WAIT;
3978
3979#if DEBUG_DCACHE
3980if ( m_debug_dcache_fsm )
3981{
3982    std::cout << "  <PROC " << name() << ".DCACHE_DIRTY_GET_PTE> Get PTE in dcache" << std::hex
3983              << " / PTE_PADDR = " << r_dcache_dirty_paddr.read() 
3984              << " / PTE_VALUE = " << pte << std::dec
3985              << " / CACHE_SET = " << set
3986              << " / CACHE_WAY = " << way << std::endl;
3987}
3988#endif
3989        break;
3990    }
3991    //////////////////////////
3992    case DCACHE_DIRTY_SC_WAIT:          // wait completion of SC for PTE Dirty bit
3993                                        // If PTE update is a success, return to IDLE state.
3994                                        // If PTE update is a failure, invalidate cache line
3995                                        // in DCACHE and invalidate the matching TLB entries.
3996    {
3997        // external coherence request
3998        if ( r_tgt_dcache_req ) 
3999        {
4000            r_dcache_fsm_cc_save = r_dcache_fsm;
4001            r_dcache_fsm         = DCACHE_CC_CHECK;
4002            break;
4003        }
4004
4005        if ( r_vci_rsp_data_error.read() )      // bus error
4006        {
4007            std::cout << "BUS ERROR in DCACHE_DIRTY_SC_WAIT state" << std::endl;
4008            std::cout << "This should not happen in this state" << std::endl;
4009            exit(0);
4010        }
4011        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
4012        {
4013            vci_rsp_fifo_dcache_get = true;
4014            r_dcache_fsm            = DCACHE_IDLE;
4015
4016#if DEBUG_DCACHE
4017if ( m_debug_dcache_fsm )
4018{
4019    std::cout << "  <PROC " << name() << ".DCACHE_DIRTY_SC_WAIT> SC completed" << std::endl;
4020}
4021#endif
4022        }
4023        break;
4024    }
4025    /////////////////////
4026    case DCACHE_CC_CHECK:   // This state is the entry point for the sub-FSM
4027                            // handling coherence requests.
4028                            // If there is a matching pending miss on the modified cache
4029                            // line this is signaled in the r_dcache_miss inval flip-flop.
4030                            // If the updated (or invalidated) cache line has copies in TLBs
4031                            // these TLB copies are invalidated.
4032                            // The return state is defined in r_dcache_fsm_cc_save
4033    {
4034        paddr_t  paddr = r_tgt_paddr.read();
4035        paddr_t  mask = ~((m_dcache_words<<2)-1);
4036
4037
4038        if( (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) and
4039            ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching pending miss
4040        {
4041            r_dcache_miss_inval = true;                 // signaling the match
4042            r_tgt_dcache_req    = false;                // coherence request completed
4043            r_tgt_dcache_rsp    = r_tgt_update.read();  // response required if update
4044            r_dcache_fsm        = r_dcache_fsm_cc_save.read();
4045
4046#if DEBUG_DCACHE
4047if ( m_debug_dcache_fsm )
4048{
4049    std::cout << "  <PROC " << name() << ".DCACHE_CC_CHECK> Coherence request matching a pending miss:"
4050              << " address = " << std::hex << paddr << std::endl;
4051}
4052#endif
4053 
4054        }
4055        else                                                    // no match for a pending miss
4056            {
4057            uint32_t   rdata;
4058            size_t         way;
4059            size_t         set;
4060            size_t         word;
4061
4062            bool           hit = r_dcache.read( paddr,
4063                                            &rdata,     // unused
4064                                            &way, 
4065                                            &set,
4066                                            &word);     // unused
4067#ifdef INSTRUMENTATION
4068m_cpt_dcache_data_read++;
4069m_cpt_dcache_dir_read++;
4070#endif
4071            r_dcache_cc_way = way;
4072            r_dcache_cc_set = set;
4073
4074            if ( hit and r_tgt_update.read() )          // hit update
4075            {
4076                r_dcache_fsm     = DCACHE_CC_UPDT;
4077                r_dcache_cc_word = r_tgt_word_min.read();
4078            }
4079            else if ( hit and not r_tgt_update.read() ) // hit inval
4080            {
4081                r_dcache_fsm     = DCACHE_CC_INVAL;
4082            }
4083            else                                        // miss can happen
4084            {
4085                r_tgt_dcache_req = false;
4086                r_tgt_dcache_rsp = r_tgt_update.read();
4087                r_dcache_fsm     = r_dcache_fsm_cc_save.read();
4088            }
4089
4090#if DEBUG_DCACHE
4091if ( m_debug_dcache_fsm )
4092{
4093   
4094    std::cout << "  <PROC " << name() << ".DCACHE_CC_CHECK> Coherence request received :"
4095              << " address = " << std::hex << paddr << std::dec;
4096    if ( hit ) 
4097    {
4098        std::cout << " / HIT" << " / way = " << way << " / set = " << set << std::endl;
4099    }
4100    else
4101    {
4102        std::cout << " / MISS" << std::endl;
4103    }
4104}
4105#endif
4106 
4107        }
4108        break;
4109    }
4110    /////////////////////
4111    case DCACHE_CC_INVAL:       // invalidate one cache line after
4112                                // invalidation of copies in TLBs
4113    {
4114        paddr_t  nline;
4115        size_t   way    = r_dcache_cc_way.read();
4116        size_t   set    = r_dcache_cc_set.read();
4117        bool     hit;
4118
4119        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )                   // selective TLB inval
4120        {
4121            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4122            r_dcache_tlb_inval_line  = r_tgt_paddr.read() >> (uint32_log2(m_dcache_words)+2);
4123            r_dcache_tlb_inval_count = 0;
4124            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
4125            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4126        }
4127        else                                                                              // actual cache line inval
4128        {
4129            if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )         // TLB flush
4130            {
4131                r_itlb.reset();
4132                r_dtlb.reset();
4133                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4134            }
4135            r_tgt_dcache_rsp = true;
4136            r_tgt_dcache_req = false;
4137            r_dcache_fsm     = r_dcache_fsm_cc_save.read();
4138 
4139            hit = r_dcache.inval( way, 
4140                                  set,
4141                                  &nline );
4142#if DEBUG_DCACHE
4143if ( m_debug_dcache_fsm )
4144{
4145    std::cout << "  <PROC " << name() << ".DCACHE_CC_INVAL> Invalidate cache line" << std::dec
4146              << " / WAY = " << way
4147              << " / SET = " << set << std::endl;
4148}
4149#endif
4150 
4151            assert(hit && "CC_INVAL way/set should be in dcache");
4152        }
4153        break;
4154    }
4155    ///////////////////
4156    case DCACHE_CC_UPDT:        // write one word per cycle (from word_min to word_max)
4157                                // and test possible copies in TLBs
4158    {
4159        size_t   word       = r_dcache_cc_word.read();
4160        size_t   way        = r_dcache_cc_way.read();
4161        size_t   set        = r_dcache_cc_set.read();
4162        paddr_t  nline      = r_tgt_paddr.read() >> (uint32_log2(m_dcache_words)+2);
4163
4164        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )                   // selective TLB inval
4165        {
4166            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4167            r_dcache_tlb_inval_line  = nline;
4168            r_dcache_tlb_inval_count = 0;
4169            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
4170            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4171        }
4172        else                                                            // cache update
4173        {
4174            if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )         // TLB flush
4175            {
4176                r_itlb.reset();
4177                r_dtlb.reset();
4178                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4179            } 
4180
4181            r_dcache.write( way,
4182                            set,
4183                            word,
4184                            r_tgt_buf[word],
4185                            r_tgt_be[word] );
4186#ifdef INSTRUMENTATION
4187m_cpt_dcache_data_write++;
4188#endif
4189            r_dcache_cc_word = word + 1;
4190
4191#if DEBUG_DCACHE
4192if ( m_debug_dcache_fsm )
4193{
4194    std::cout << "  <PROC " << name() << ".DCACHE_CC_UPDT> Update one word" << std::dec
4195              << " / WAY = " << way
4196              << " / SET = " << set
4197              << " / WORD = " << word
4198              << " / VALUE = " << std::hex << r_tgt_buf[word] << std::endl;
4199}
4200#endif
4201            if ( word == r_tgt_word_max.read() )        // last word
4202            {
4203                r_tgt_dcache_rsp = true;
4204                r_tgt_dcache_req = false;
4205                r_dcache_fsm     = r_dcache_fsm_cc_save.read();
4206            }
4207        }
4208
4209        break;
4210    }
4211    ///////////////////////////
4212    case DCACHE_INVAL_TLB_SCAN:         // Scan sequencially all TLB entries for both ITLB & DTLB
4213                                        // It makes the assumption that (m_itlb_sets == m_dtlb_sets)
4214                                        // and (m_itlb_ways == m_dtlb_ways)
4215                                        // We enter this state when a DCACHE line is modified,
4216                                        // and there is a copy in itlb or dtlb.
4217                                        // It can be caused by:
4218                                        // - a coherence inval or updt transaction,
4219                                        // - a line inval caused by a cache miss
4220                                        // - a processor XTN inval request,
4221                                        // - a WRITE hit,
4222                                        // - a Dirty bit update failure
4223                                        // Input arguments are:
4224                                        // - r_dcache_tlb_inval_line
4225                                        // - r_dcache_tlb_inval_count
4226                                        // - r_dcache_fsm_cc_save
4227    {
4228        paddr_t line = r_dcache_tlb_inval_line.read();                  // nline
4229        size_t  way  = r_dcache_tlb_inval_count.read()/m_itlb_sets;     // way
4230        size_t  set  = r_dcache_tlb_inval_count.read()%m_itlb_sets;     // set
4231        bool    ok;
4232
4233        ok = r_itlb.inval( line,
4234                            way,
4235                            set );
4236#if DEBUG_DCACHE
4237if ( m_debug_dcache_fsm and ok )
4238{
4239    std::cout << "  <PROC " << name() << ".DCACHE_INVAL_TLB_SCAN> Invalidate ITLB entry:" << std::hex
4240              << " line = " << line << std::dec
4241              << " / set = " << set
4242              << " / way = " << way << std::endl;
4243    r_itlb.printTrace();
4244}
4245#endif
4246        ok = r_dtlb.inval( line,
4247                           way,
4248                           set );
4249#if DEBUG_DCACHE
4250if ( m_debug_dcache_fsm and ok )
4251{
4252    std::cout << "  <PROC " << name() << ".DCACHE_INVAL_TLB_SCAN> Invalidate DTLB entry:" << std::hex
4253              << " line = " << line << std::dec
4254              << " / set = " << set
4255              << " / way = " << way << std::endl;
4256    r_dtlb.printTrace();
4257}
4258#endif
4259
4260        // return to the calling state when TLB inval completed
4261        if ( r_dcache_tlb_inval_count.read() == ((m_dtlb_sets*m_dtlb_ways)-1) )
4262        {
4263            r_dcache_fsm = r_dcache_fsm_scan_save.read();
4264        }
4265        r_dcache_tlb_inval_count = r_dcache_tlb_inval_count.read() + 1;
4266        break;
4267    }   
4268    } // end switch r_dcache_fsm
4269
4270    ///////////////// wbuf update //////////////////////////////////////////////////////
4271    r_wbuf.update();
4272
4273    //////////////// test processor frozen /////////////////////////////////////////////
4274    // The simulation exit if the number of consecutive frozen cycles
4275    // is larger than the m_max_frozen_cycles (constructor parameter)
4276    if ( (m_ireq.valid and not m_irsp.valid) or (m_dreq.valid and not m_drsp.valid) )       
4277    {
4278        m_cpt_frz_cycles++;             // used for instrumentation
4279        m_cpt_stop_simulation++;        // used for debug
4280        if ( m_cpt_stop_simulation > m_max_frozen_cycles )
4281        {
4282            std::cout << std::dec << "ERROR in CC_VCACHE_WRAPPER " << name() << std::endl
4283                      << " stop at cycle " << m_cpt_total_cycles << std::endl
4284                      << " frozen since cycle " << m_cpt_total_cycles - m_max_frozen_cycles << std::endl;
4285                      r_iss.dump();
4286            exit(1);
4287        }
4288    }
4289    else
4290    {
4291        m_cpt_stop_simulation = 0;
4292    }
4293
4294    /////////// execute one iss cycle /////////////////////////////////
4295    {
4296    uint32_t it = 0;
4297    for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if(p_irq[i].read()) it |= (1<<i);
4298    r_iss.executeNCycles(1, m_irsp, m_drsp, it);
4299    }
4300
4301    ////////////////////////////////////////////////////////////////////////////
4302    // The VCI_CMD FSM controls the following ressources:
4303    // - r_vci_cmd_fsm
4304    // - r_vci_cmd_min
4305    // - r_vci_cmd_max
4306    // - r_vci_cmd_cpt
4307    // - r_vci_cmd_imiss_prio
4308    // - wbuf (reset)
4309    // - r_icache_miss_req (reset)
4310    // - r_icache_unc_req (reset)
4311    // - r_dcache_vci_miss_req (reset)
4312    // - r_dcache_vci_unc_req (reset)
4313    // - r_dcache_vci_sc_req (reset)
4314    //
4315    // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
4316    // There is 6 request types, with the following priorities :
4317    // 1 - Data Read Miss         : r_dcache_vci_miss_req and miss in the write buffer
4318    // 2 - Data Read Uncachable   : r_dcache_vci_unc_req 
4319    // 3 - Instruction Miss       : r_icache_miss_req and miss in the write buffer
4320    // 4 - Instruction Uncachable : r_icache_unc_req
4321    // 5 - Data Write             : r_wbuf.rok()     
4322    // 6 - Data Store Conditionnal: r_dcache_vci_sc_req
4323    //
4324    // As we want to support several simultaneous VCI transactions, the VCI_CMD_FSM
4325    // and the VCI_RSP_FSM are fully desynchronized.
4326    //
4327    // VCI formats:
4328    // According to the VCI advanced specification, all read requests packets
4329    // (data Uncached, Miss data, instruction Uncached, Miss instruction)
4330    // are one word packets.
4331    // For write burst packets, all words are in the same cache line,
4332    // and addresses must be contiguous (the BE field is 0 in case of "holes").
4333    // The sc command packet implements actually a compare-and-swap mechanism
4334    // and the packet contains two flits.
4335    ////////////////////////////////////////////////////////////////////////////////////
4336
4337    switch ( r_vci_cmd_fsm.read() ) 
4338    {
4339        //////////////
4340        case CMD_IDLE:
4341        {
4342            // r_dcache_vci_miss_req and r_icache_miss_req require both a write_buffer access
4343            // to check a possible pending write on the same cache line.
4344            // As there is only one possible access per cycle to write buffer, we implement
4345            // a round-robin priority for this access, using the r_vci_cmd_imiss_prio flip-flop.
4346
4347            size_t      wbuf_min;
4348            size_t      wbuf_max;
4349
4350            bool dcache_miss_req = r_dcache_vci_miss_req.read()
4351                 and ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() );
4352
4353            bool icache_miss_req = r_icache_miss_req.read()
4354                 and ( not r_dcache_vci_miss_req.read() or r_vci_cmd_imiss_prio.read() );
4355
4356            // 1 - Data Read Miss
4357            if ( dcache_miss_req and r_wbuf.miss(r_dcache_vci_paddr.read()) )
4358            {
4359                r_vci_cmd_fsm         = CMD_DATA_MISS;
4360                r_dcache_vci_miss_req = false;
4361                r_vci_cmd_imiss_prio  = true;
4362//                m_cpt_dmiss_transaction++;
4363            }
4364            // 2 - Data Read Uncachable
4365            else if ( r_dcache_vci_unc_req.read() )
4366            {
4367                r_vci_cmd_fsm        = CMD_DATA_UNC;
4368                r_dcache_vci_unc_req = false;
4369//                m_cpt_dunc_transaction++;
4370            }
4371            // 3 - Instruction Miss
4372            else if ( icache_miss_req and r_wbuf.miss(r_icache_vci_paddr.read()) )
4373            {
4374                r_vci_cmd_fsm        = CMD_INS_MISS;
4375                r_icache_miss_req    = false;
4376                r_vci_cmd_imiss_prio = false;
4377//                m_cpt_imiss_transaction++;
4378            }
4379            // 4 - Instruction Uncachable
4380            else if ( r_icache_unc_req.read() )
4381            {
4382                r_vci_cmd_fsm    = CMD_INS_UNC;
4383                r_icache_unc_req = false;
4384//                m_cpt_iunc_transaction++;
4385            }
4386            // 5 - Data Write
4387            else if ( r_wbuf.rok(&wbuf_min, &wbuf_max) )
4388            {
4389                r_vci_cmd_fsm       = CMD_DATA_WRITE;
4390                r_vci_cmd_cpt       = wbuf_min;
4391                r_vci_cmd_min       = wbuf_min;
4392                r_vci_cmd_max       = wbuf_max;
4393//                m_cpt_write_transaction++;
4394//                m_length_write_transaction += (wbuf_max-wbuf_min+1);
4395            }
4396            // 6 - Data Store Conditionnal
4397            else if ( r_dcache_vci_sc_req.read() )
4398            {
4399                r_vci_cmd_fsm       = CMD_DATA_SC;
4400                r_dcache_vci_sc_req = false;
4401                r_vci_cmd_cpt       = 0;
4402//                m_cpt_sc_transaction++;
4403            }
4404            break;
4405        }
4406        ////////////////////
4407        case CMD_DATA_WRITE:
4408        {
4409            if ( p_vci_ini_d.cmdack.read() )
4410            {
4411//                m_conso_wbuf_read++;
4412                r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
4413                if (r_vci_cmd_cpt == r_vci_cmd_max) // last flit sent
4414                {
4415                    r_vci_cmd_fsm = CMD_IDLE ;
4416                    r_wbuf.sent() ;
4417                }
4418            }
4419            break;
4420        }
4421        /////////////////
4422        case CMD_DATA_SC:
4423        {
4424            // The SC VCI command contains two flits
4425            if ( p_vci_ini_d.cmdack.read() )
4426            {
4427               r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
4428               if (r_vci_cmd_cpt == 1) r_vci_cmd_fsm = CMD_IDLE ;
4429            }
4430            break;
4431        }
4432        //////////////////
4433        case CMD_INS_MISS:
4434        case CMD_INS_UNC:
4435        case CMD_DATA_MISS:
4436        case CMD_DATA_UNC:
4437        {
4438            // all read VCI commands contain one single flit
4439            if ( p_vci_ini_d.cmdack.read() )  r_vci_cmd_fsm = CMD_IDLE;
4440            break;
4441        }
4442
4443    } // end  switch r_vci_cmd_fsm
4444
4445    //////////////////////////////////////////////////////////////////////////
4446    // The VCI_RSP FSM controls the following ressources:
4447    // - r_vci_rsp_fsm:
4448    // - r_vci_rsp_fifo_icache (push)
4449    // - r_vci_rsp_fifo_dcache (push)
4450    // - r_vci_rsp_data_error (set)
4451    // - r_vci_rsp_ins_error (set)
4452    // - r_vci_rsp_cpt
4453    //
4454    // As the VCI_RSP and VCI_CMD are fully desynchronized to support several
4455    // simultaneous VCI transactions, this FSM uses the VCI TRDID field
4456    // to identify the transactions.
4457    //
4458    // VCI vormat:
4459    // This component checks the response packet length and accepts only
4460    // single word packets for write response packets.
4461    //
4462    // Error handling:
4463    // This FSM analyzes the VCI error code and signals directly the Write Bus Error.
4464    // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error
4465    // flip_flop and the error is signaled by the DCACHE FSM. 
4466    // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
4467    // flip_flop and the error is signaled by the ICACHE FSM. 
4468    // In case of Cleanup Error, the simulation stops with an error message...
4469    //////////////////////////////////////////////////////////////////////////
4470
4471    switch ( r_vci_rsp_fsm.read() ) 
4472    {
4473    //////////////
4474    case RSP_IDLE:
4475    {
4476        if ( p_vci_ini_d.rspval.read() )
4477        {
4478            r_vci_rsp_cpt = 0;
4479
4480            if ( (p_vci_ini_d.rtrdid.read() >> (vci_param::T-1)) != 0 ) // Write transaction
4481            {
4482                r_vci_rsp_fsm = RSP_DATA_WRITE;
4483            }
4484            else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_MISS )
4485            {
4486                r_vci_rsp_fsm = RSP_INS_MISS;
4487            }
4488            else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_UNC )
4489            {
4490                r_vci_rsp_fsm = RSP_INS_UNC;
4491            }
4492            else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_MISS )
4493            {
4494                r_vci_rsp_fsm = RSP_DATA_MISS;
4495            }
4496            else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_UNC )
4497            {
4498                r_vci_rsp_fsm = RSP_DATA_UNC;
4499            }
4500            else
4501            {
4502                assert(false and "Unexpected VCI response");
4503            }
4504        }
4505        break;
4506    }
4507        //////////////////
4508        case RSP_INS_MISS:
4509        {
4510            if ( p_vci_ini_d.rspval.read() )
4511            {
4512                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4513                {
4514                    r_vci_rsp_ins_error = true;
4515                    if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
4516                }
4517                else                                        // no error reported
4518                {
4519                    if ( r_vci_rsp_fifo_icache.wok() )
4520                    {
4521                        assert( (r_vci_rsp_cpt.read() < m_icache_words) and
4522                        "The VCI response packet for instruction miss is too long" );
4523
4524                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
4525                        vci_rsp_fifo_icache_put       = true,
4526                        vci_rsp_fifo_icache_data      = p_vci_ini_d.rdata.read();
4527                        if ( p_vci_ini_d.reop.read() )
4528                        {
4529                            assert( (r_vci_rsp_cpt.read() == m_icache_words - 1) and
4530                            "The VCI response packet for instruction miss is too short");
4531
4532                            r_vci_rsp_fsm    = RSP_IDLE;
4533                        }
4534                    }
4535                }
4536            }
4537            break;
4538        }
4539        /////////////////
4540        case RSP_INS_UNC:
4541        {
4542            if (p_vci_ini_d.rspval.read() )
4543            {
4544                assert( p_vci_ini_d.reop.read() and
4545                "illegal VCI response packet for uncachable instruction");
4546
4547                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4548                {
4549                    r_vci_rsp_ins_error = true;
4550                    r_vci_rsp_fsm = RSP_IDLE;
4551                }
4552                else                                         // no error reported
4553                {
4554                    if ( r_vci_rsp_fifo_icache.wok())
4555                    {
4556                        vci_rsp_fifo_icache_put       = true;
4557                        vci_rsp_fifo_icache_data      = p_vci_ini_d.rdata.read();
4558                        r_vci_rsp_fsm = RSP_IDLE;
4559                    }
4560                }
4561            }
4562            break;
4563        }
4564        ///////////////////
4565        case RSP_DATA_MISS:
4566        {
4567            if ( p_vci_ini_d.rspval.read() )
4568            {
4569                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4570                {
4571                    r_vci_rsp_data_error = true;
4572                    if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
4573                }
4574                else                                        // no error reported
4575                {
4576                    if ( r_vci_rsp_fifo_dcache.wok() )
4577                    {
4578                        assert( (r_vci_rsp_cpt.read() < m_dcache_words) and
4579                        "The VCI response packet for data miss is too long");
4580
4581                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
4582                        vci_rsp_fifo_dcache_put       = true,
4583                        vci_rsp_fifo_dcache_data      = p_vci_ini_d.rdata.read();
4584                        if ( p_vci_ini_d.reop.read() )
4585                        {
4586                            assert( (r_vci_rsp_cpt.read() == m_dcache_words - 1) and
4587                            "The VCI response packet for data miss is too short");
4588
4589                            r_vci_rsp_fsm     = RSP_IDLE;
4590                        }
4591                    }
4592                }
4593            }
4594            break;
4595        }
4596        //////////////////
4597        case RSP_DATA_UNC:
4598        {
4599            if (p_vci_ini_d.rspval.read() )
4600            {
4601                assert( p_vci_ini_d.reop.read() and
4602                "illegal VCI response packet for uncachable read data");
4603
4604                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4605                {
4606                    r_vci_rsp_data_error = true;
4607                    r_vci_rsp_fsm = RSP_IDLE;
4608                }
4609                else                                         // no error reported
4610                {
4611                    if ( r_vci_rsp_fifo_dcache.wok())
4612                    {
4613                        vci_rsp_fifo_dcache_put       = true;
4614                        vci_rsp_fifo_dcache_data      = p_vci_ini_d.rdata.read();
4615                        r_vci_rsp_fsm = RSP_IDLE;
4616                    }
4617                }
4618            }
4619            break;
4620        }
4621        ////////////////////
4622        case RSP_DATA_WRITE:
4623        {
4624            if (p_vci_ini_d.rspval.read())
4625            {
4626                assert( p_vci_ini_d.reop.read() and
4627                "a VCI response packet must contain one flit for a write transaction");
4628
4629                r_vci_rsp_fsm = RSP_IDLE;
4630                uint32_t   wbuf_index = p_vci_ini_d.rtrdid.read() - (1<<(vci_param::T-1));
4631                bool       cacheable  = r_wbuf.completed(wbuf_index);
4632                if ( not cacheable ) r_dcache_pending_unc_write = false;
4633                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 ) r_iss.setWriteBerr();
4634            }
4635            break;
4636        }
4637    } // end switch r_vci_rsp_fsm
4638
4639    /////////////////////////////////////////////////////////////////////////////////////
4640    // The CLEANUP FSM is in charge to send the cleanup commands on the coherence
4641    // network. It has two clients (DCACHE FSM and ICACHE FSM) that are served
4642    // with a round-robin priority. All cleanup commands are registered in the
4643    // r_cleanup_buffer, because we must avoid to send a Read Miss command
4644    // for line (X) if there is a pending cleanup for line (X): the r_cleanup_buffer
4645    // is tested by the ICACHE FSM and DCACHE FSM before posting a miss request.
4646    // The CLEANUP FSM resets the r_*cache_cleanup request flip-flops as soon as
4647    // the request has been sent and registered in the buffer.
4648    // The buffer itself is cleared when the cleanup response is received.
4649    // We use an assocative registration buffer (CAM) in order to support several
4650    // simultaneous cleanup transactions (up to 4 simultaneous clenups).
4651    // The VCI TRDID field is used to distinguish data/instruction cleanups:
4652    // - if data cleanup        : TRDID = 2*index + 0
4653    // - if instruction cleanup : TRDID = 2*index + 1
4654    /////////////////////////////////////////////////////////////////////////////////////
4655
4656    switch ( r_cleanup_fsm.read() ) 
4657    {
4658        ///////////////////////
4659        case CLEANUP_DATA_IDLE:     // dcache has highest priority
4660        {
4661            size_t  index = 0;
4662            bool    ok;
4663            if ( r_dcache_cleanup_req.read() )      // dcache request
4664            {
4665                ok = r_cleanup_buffer.write( r_dcache_cleanup_line.read(), 
4666                                             &index );   
4667                if ( ok )   // successful registration
4668                {
4669                    r_cleanup_fsm   = CLEANUP_DATA_GO; 
4670                    r_cleanup_trdid = index<<1;
4671                }
4672            }
4673            else if ( r_icache_cleanup_req.read() ) // icache request
4674            {
4675                ok = r_cleanup_buffer.write( r_icache_cleanup_line.read(), 
4676                                             &index );   
4677                if ( ok )   // successful registration
4678                {
4679                    r_cleanup_fsm   = CLEANUP_INS_GO; 
4680                    r_cleanup_trdid = (index<<1) + 1;
4681                }
4682            }
4683            break;
4684        }
4685        //////////////////////
4686        case CLEANUP_INS_IDLE:     // icache has highest priority
4687        {
4688            size_t  index = 0;
4689            bool    ok;
4690            if ( r_icache_cleanup_req.read() )      // icache request
4691            {
4692                ok = r_cleanup_buffer.write( r_icache_cleanup_line.read(),
4693                                             &index );   
4694                if ( ok )   // successful registration
4695                {
4696                    r_cleanup_fsm   = CLEANUP_INS_GO;
4697                    r_cleanup_trdid = (index<<1) + 1;
4698                }
4699            }
4700            else if ( r_dcache_cleanup_req.read() ) // dcache request
4701            {
4702                ok = r_cleanup_buffer.write( r_dcache_cleanup_line.read(),
4703                                             &index );   
4704                if ( ok )   // successful registration
4705                {
4706                    r_cleanup_fsm   = CLEANUP_DATA_GO;
4707                    r_cleanup_trdid = index<<1;
4708                }
4709            }
4710            break;
4711        }
4712        /////////////////////
4713        case CLEANUP_DATA_GO:
4714        {
4715            if ( p_vci_ini_c.cmdack.read() )
4716            {
4717                r_cleanup_fsm        = CLEANUP_INS_IDLE;
4718                r_dcache_cleanup_req = false;
4719
4720#if DEBUG_CLEANUP
4721if ( m_debug_cleanup_fsm )
4722{
4723    std::cout << "  <PROC " << name() << ".CLEANUP_DATA_GO> Cleanup request for icache:" << std::hex
4724              << " address = " << (r_dcache_cleanup_line.read()*m_dcache_words*4)
4725              << " / trdid = " << std::dec << r_cleanup_trdid.read() << std::endl;
4726}
4727#endif
4728            }
4729            break;
4730        }
4731        ////////////////////
4732        case CLEANUP_INS_GO:
4733        {
4734            if ( p_vci_ini_c.cmdack.read() )
4735            {
4736                r_cleanup_fsm        = CLEANUP_DATA_IDLE;
4737                r_icache_cleanup_req = false;
4738
4739#if DEBUG_CLEANUP
4740if ( m_debug_cleanup_fsm )
4741{
4742    std::cout << "  <PROC " << name() << ".CLEANUP_INS_GO> Cleanup request for dcache:" << std::hex
4743              << " address = " << (r_icache_cleanup_line.read()*m_icache_words*4)
4744              << " / trdid = " << std::dec << r_cleanup_trdid.read() << std::endl;
4745}
4746#endif
4747            }
4748            break;
4749        }
4750    } // end switch CLEANUP FSM
4751
4752    //////////////// Handling  cleanup responses //////////////////
4753    if ( p_vci_ini_c.rspval.read() )   
4754    {
4755        r_cleanup_buffer.inval( p_vci_ini_c.rtrdid.read() >> 1);
4756    }
4757
4758    ///////////////// Response FIFOs update  //////////////////////
4759    r_vci_rsp_fifo_icache.update(vci_rsp_fifo_icache_get,
4760                                 vci_rsp_fifo_icache_put,
4761                                 vci_rsp_fifo_icache_data);
4762
4763    r_vci_rsp_fifo_dcache.update(vci_rsp_fifo_dcache_get,
4764                                 vci_rsp_fifo_dcache_put,
4765                                 vci_rsp_fifo_dcache_data);
4766} // end transition()
4767
4768///////////////////////
4769tmpl(void)::genMoore()
4770///////////////////////
4771{
4772    ////////////////////////////////////////////////////////////////
4773    // VCI initiator command on the coherence network (cleanup)
4774    // it depends on the CLEANUP FSM state
4775
4776    paddr_t  cleanup_nline;
4777    paddr_t  address;
4778
4779    if ( r_cleanup_fsm.read() == CLEANUP_DATA_GO )
4780    {
4781        cleanup_nline = r_dcache_cleanup_line.read();
4782        address       = (m_x_width + m_y_width) ? (cleanup_nline * m_dcache_words * 4    ) >>
4783                                                  (vci_param::- m_x_width - m_y_width ) : 0;
4784    }
4785    else if ( r_cleanup_fsm.read() == CLEANUP_INS_GO )
4786    {
4787        cleanup_nline = r_icache_cleanup_line.read();
4788        address       = (m_x_width + m_y_width) ? (cleanup_nline * m_icache_words * 4    ) >>
4789                                                  (vci_param::- m_x_width - m_y_width ) : 0;
4790    }
4791    else
4792    {
4793        cleanup_nline = 0;
4794        address       = 0;
4795    }
4796
4797    address           <<= vci_param::S - m_x_width - m_y_width;
4798    address            |= m_memory_cache_local_id;
4799    address           <<= vci_param::N - vci_param::S;
4800
4801    p_vci_ini_c.cmdval  = ((r_cleanup_fsm.read() == CLEANUP_DATA_GO) or
4802                           (r_cleanup_fsm.read() == CLEANUP_INS_GO) );
4803    p_vci_ini_c.address = address;
4804    p_vci_ini_c.wdata   = (uint32_t) cleanup_nline;
4805    p_vci_ini_c.be      = (cleanup_nline >> 32) & 0x3;
4806    p_vci_ini_c.plen    = 4;
4807    p_vci_ini_c.cmd     = vci_param::CMD_WRITE;
4808    p_vci_ini_c.trdid   = r_cleanup_trdid.read();
4809    p_vci_ini_c.pktid   = 0;
4810    p_vci_ini_c.srcid   = m_srcid_c;
4811    p_vci_ini_c.cons    = false;
4812    p_vci_ini_c.wrap    = false;
4813    p_vci_ini_c.contig  = false;
4814    p_vci_ini_c.clen    = 0;
4815    p_vci_ini_c.cfixed  = false;
4816    p_vci_ini_c.eop     = true;
4817
4818    /////////////////////////////////////////////////////////////////
4819    // VCI initiator response on the coherence network (cleanup)
4820    // We always consume the response, and we don't use it.
4821
4822    p_vci_ini_c.rspack  = true;
4823
4824    /////////////////////////////////////////////////////////////////
4825    // VCI initiator command on the direct network
4826    // it depends on the CMD FSM state
4827
4828    p_vci_ini_d.pktid  = 0;
4829    p_vci_ini_d.srcid  = m_srcid_d;
4830    p_vci_ini_d.cons   = (r_vci_cmd_fsm.read() == CMD_DATA_SC);
4831    p_vci_ini_d.contig = not (r_vci_cmd_fsm.read() == CMD_DATA_SC);
4832    p_vci_ini_d.wrap   = false;
4833    p_vci_ini_d.clen   = 0;
4834    p_vci_ini_d.cfixed = false;
4835
4836    switch ( r_vci_cmd_fsm.read() ) {
4837
4838    case CMD_IDLE:
4839        p_vci_ini_d.cmdval  = false;
4840        p_vci_ini_d.address = 0;
4841        p_vci_ini_d.wdata   = 0;
4842        p_vci_ini_d.be      = 0;
4843        p_vci_ini_d.trdid   = 0;
4844        p_vci_ini_d.plen    = 0;
4845        p_vci_ini_d.cmd     = vci_param::CMD_NOP;
4846        p_vci_ini_d.eop     = false;
4847        break;
4848
4849    case CMD_INS_MISS:
4850        p_vci_ini_d.cmdval  = true;
4851        p_vci_ini_d.address = r_icache_vci_paddr.read() & m_icache_yzmask;
4852        p_vci_ini_d.wdata   = 0;
4853        p_vci_ini_d.be      = 0xF;
4854        p_vci_ini_d.trdid   = TYPE_INS_MISS;
4855        p_vci_ini_d.plen    = m_icache_words<<2;
4856        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4857        p_vci_ini_d.eop     = true;
4858        break;
4859
4860    case CMD_INS_UNC:
4861        p_vci_ini_d.cmdval  = true;
4862        p_vci_ini_d.address = r_icache_vci_paddr.read() & ~0x3;
4863        p_vci_ini_d.wdata   = 0;
4864        p_vci_ini_d.be      = 0xF;
4865        p_vci_ini_d.trdid   = TYPE_INS_UNC;
4866        p_vci_ini_d.plen    = 4;
4867        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4868        p_vci_ini_d.eop     = true;
4869        break;
4870
4871    case CMD_DATA_MISS:
4872        p_vci_ini_d.cmdval  = true;
4873        p_vci_ini_d.address = r_dcache_vci_paddr.read() & m_dcache_yzmask;
4874        p_vci_ini_d.wdata   = 0;
4875        p_vci_ini_d.be      = 0xF;
4876        p_vci_ini_d.trdid   = TYPE_DATA_MISS;
4877        p_vci_ini_d.plen    = m_dcache_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_DATA_UNC:
4883        p_vci_ini_d.cmdval  = true;
4884        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
4885        p_vci_ini_d.wdata   = 0;
4886        p_vci_ini_d.be      = r_dcache_vci_unc_be.read();
4887        p_vci_ini_d.trdid   = TYPE_DATA_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_WRITE:
4894        p_vci_ini_d.cmdval  = true;
4895        p_vci_ini_d.address = r_wbuf.getAddress(r_vci_cmd_cpt.read()) & ~0x3;
4896        p_vci_ini_d.wdata   = r_wbuf.getData(r_vci_cmd_cpt.read());
4897        p_vci_ini_d.be      = r_wbuf.getBe(r_vci_cmd_cpt.read());
4898        p_vci_ini_d.trdid   = r_wbuf.getIndex() + (1<<(vci_param::T-1));
4899        p_vci_ini_d.plen    = (r_vci_cmd_max.read() - r_vci_cmd_min.read() + 1) << 2;
4900        p_vci_ini_d.cmd     = vci_param::CMD_WRITE;
4901        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
4902        break;
4903
4904    case CMD_DATA_SC:
4905        p_vci_ini_d.cmdval  = true;
4906        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
4907        if ( r_vci_cmd_cpt.read() == 0 ) p_vci_ini_d.wdata = r_dcache_vci_sc_old.read();
4908        else                             p_vci_ini_d.wdata = r_dcache_vci_sc_new.read();
4909        p_vci_ini_d.be      = 0xF;
4910        p_vci_ini_d.trdid   = TYPE_DATA_UNC; 
4911        p_vci_ini_d.plen    = 8;
4912        p_vci_ini_d.cmd     = vci_param::CMD_STORE_COND;
4913        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == 1);
4914        break;     
4915    } // end switch r_vci_cmd_fsm
4916
4917    //////////////////////////////////////////////////////////
4918    // VCI initiator response on the direct network
4919    // it depends on the VCI RSP state
4920
4921    switch (r_vci_rsp_fsm.read() )
4922    {
4923        case RSP_DATA_WRITE : p_vci_ini_d.rspack = true; break;
4924        case RSP_INS_MISS   : p_vci_ini_d.rspack = r_vci_rsp_fifo_icache.wok(); break;
4925        case RSP_INS_UNC    : p_vci_ini_d.rspack = r_vci_rsp_fifo_icache.wok(); break;
4926        case RSP_DATA_MISS  : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
4927        case RSP_DATA_UNC   : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
4928        case RSP_IDLE       : p_vci_ini_d.rspack = false; break;
4929    } // end switch r_vci_rsp_fsm
4930
4931    ////////////////////////////////////////////////////////////////
4932    // VCI target command and response on the coherence network
4933    switch ( r_tgt_fsm.read() ) 
4934    {
4935    case TGT_IDLE:
4936    case TGT_UPDT_WORD:
4937    case TGT_UPDT_DATA:
4938        p_vci_tgt_c.cmdack  = true;
4939        p_vci_tgt_c.rspval  = false;
4940        break;
4941
4942    case TGT_RSP_BROADCAST:
4943        p_vci_tgt_c.cmdack  = false;
4944        p_vci_tgt_c.rspval  = not r_tgt_icache_req.read() and not r_tgt_dcache_req.read()
4945                              and ( r_tgt_icache_rsp.read() or r_tgt_dcache_rsp.read() );
4946        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
4947        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
4948        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
4949        p_vci_tgt_c.rdata   = 0;
4950        p_vci_tgt_c.rerror  = 0;
4951        p_vci_tgt_c.reop    = true;
4952        break;
4953
4954    case TGT_RSP_ICACHE:
4955        p_vci_tgt_c.cmdack  = false;
4956        p_vci_tgt_c.rspval  = not r_tgt_icache_req.read() and r_tgt_icache_rsp.read();
4957        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
4958        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
4959        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
4960        p_vci_tgt_c.rdata   = 0;
4961        p_vci_tgt_c.rerror  = 0;
4962        p_vci_tgt_c.reop    = true;
4963        break;
4964
4965    case TGT_RSP_DCACHE:
4966        p_vci_tgt_c.cmdack  = false;
4967        p_vci_tgt_c.rspval  = not r_tgt_dcache_req.read() and 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_REQ_BROADCAST:
4977    case TGT_REQ_ICACHE:
4978    case TGT_REQ_DCACHE:
4979        p_vci_tgt_c.cmdack  = false;
4980        p_vci_tgt_c.rspval  = false;
4981        break;
4982
4983    } // end switch TGT_FSM
4984} // end genMoore
4985
4986}}
4987
4988// Local Variables:
4989// tab-width: 4
4990// c-basic-offset: 4
4991// c-file-offsets:((innamespace . 0)(inline-open . 0))
4992// indent-tabs-mode: nil
4993// End:
4994
4995// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
Note: See TracBrowser for help on using the repository browser.