source: branches/reconfiguration/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp @ 970

Last change on this file since 970 was 970, checked in by cfuguet, 10 years ago

bugfix in vci_cc_vcache_wrapper: remove a wrong assert condition

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