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

Last change on this file since 740 was 740, checked in by alain, 10 years ago

Cosmetic

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