source: trunk/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp @ 789

Last change on this file since 789 was 789, checked in by meunier, 8 years ago

Trunk:

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