source: branches/fault_tolerance/module/internal_component/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp @ 684

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

Merging trunk modifications (r678) into fault-tolerance branch

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