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

Last change on this file since 1062 was 1061, checked in by alain, 5 years ago

Fix a bug in the LLSC reservation FSM: the r_llsc_count (lifetime counter)
was not properly updated, resulting in an unexpected reservation invalidation.
This caused an abnormal failure in the NON BLOCKING hal_remote_atomic_cas()
function in ALMOS-MKH.

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