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

Last change on this file since 352 was 352, checked in by cfuguet, 11 years ago

Bugfix in vci_cc_vcache_wrapper_v4:
In case of SC or CAS command, the bit cons must be set and the
bit contig must be unset. In this two kind of commands, the
command packet is two flits long and the address must be
constant.

This bugfix has been already commited for tsar version 5.

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