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

Last change on this file since 656 was 656, checked in by cfuguet, 9 years ago

TSAR FAULT TOLERANCE BRANCH

vci_simple_rom:

  • Introducing ROM component which can discard most significant bits when calling the load function of the loader. This allows us to replicate some code in several cluster as we can mask the cluster ID bits of the address.

vci_cc_vcache_wrapper:

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