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

Last change on this file since 288 was 288, checked in by joannou, 11 years ago

Bug fix in vci_cc_vcache_wrapper_v4 : unwanted reset of the r_dcache_pending_unc_write flag
Description : an unc write is registered by the DCACHE FSM in the write buffer,
then a cacheable write resets the flag (THIS SHOULD NOT HAPPEN) and is
registered in the write buffer. Then, a second unc write is also registered in
the write buffer (could be avoided by the flag being correctly set). The CMD
FSM then becomes ready to consume from the write buffer and chooses to send the
second unc write first. (This bug appeared when trying to dsiplay giet_vm boot
debug messages in a tsarv4_generic_mmu platform with a 1 cluster / 4 processors
configuration)

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