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

Last change on this file since 197 was 197, checked in by almaless, 12 years ago

Listen to CC-Requests while waiting

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