source: branches/v5/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp @ 461

Last change on this file since 461 was 461, checked in by cfuguet, 11 years ago

Bugfix in vci_cc_vcache_wrapper:

  • In the states DCACHE/ICACHE CC_UPDT the FSM returns to the state CC_CHECK only when the cc_send_req is occupied.

We must not return to the CC_CHECK state if not ROK of the
DATA FIFO because the counter word counter will be reset.

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