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

Last change on this file since 484 was 484, checked in by devigne, 9 years ago

Fixing deadlock :
L1 cache can be interrupted for coherency processing (UPDT, INVAL, BROADCAST)
only if CC_SEND_FSM is available.

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