source: branches/v5/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp @ 299

Last change on this file since 299 was 299, checked in by alain, 11 years ago

bug fixing: coherence interrupt must be taken in the MISS_DIR_UPDT states.

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