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

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

Modification in vci_cc_vcache_wrapper:

  • Optimization in DCACHE/ICACHE CC_CHECK state. We can handle a CLACK and a CC request if the latter does a MISS match. This is because the CC request doing MISS match does not need to access the directory
File size: 233.1 KB
Line 
1/* -*- c++ -*-
2 * File : vci_cc_vcache_wrapper.cpp
3 * Copyright (c) UPMC, Lip6, SoC
4 * Authors : Alain GREINER, Yang GAO
5 *
6 * SOCLIB_LGPL_HEADER_BEGIN
7 *
8 * This file is part of SoCLib, GNU LGPLv2.1.
9 *
10 * SoCLib is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; version 2.1 of the License.
13 *
14 * SoCLib is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with SoCLib; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 *
24 * SOCLIB_LGPL_HEADER_END
25 *
26 * Maintainers: cesar.fuguet-tortolero@lip6.fr
27 *              alexandre.joannou@lip6.fr
28 */
29
30#include <cassert>
31#include "arithmetics.h"
32#include "../include/vci_cc_vcache_wrapper.h"
33
34#define DEBUG_DCACHE            1
35#define DEBUG_ICACHE            1
36#define DEBUG_CMD               0
37
38namespace soclib {
39namespace caba {
40
41namespace {
42const char *icache_fsm_state_str[] = {
43        "ICACHE_IDLE",
44
45        "ICACHE_XTN_TLB_FLUSH",
46        "ICACHE_XTN_CACHE_FLUSH",
47        "ICACHE_XTN_CACHE_FLUSH_GO",
48        "ICACHE_XTN_TLB_INVAL",
49        "ICACHE_XTN_CACHE_INVAL_VA",
50        "ICACHE_XTN_CACHE_INVAL_PA",
51        "ICACHE_XTN_CACHE_INVAL_GO",
52
53        "ICACHE_TLB_WAIT",
54
55        "ICACHE_MISS_SELECT",
56        "ICACHE_MISS_CLEAN",
57        "ICACHE_MISS_WAIT",
58        "ICACHE_MISS_DATA_UPDT",
59        "ICACHE_MISS_DIR_UPDT",
60
61        "ICACHE_UNC_WAIT",
62
63        "ICACHE_CC_CHECK",
64        "ICACHE_CC_UPDT",
65        "ICACHE_CC_INVAL",
66    };
67
68const char *dcache_fsm_state_str[] = {
69        "DCACHE_IDLE",
70
71        "DCACHE_TLB_MISS",
72        "DCACHE_TLB_PTE1_GET",
73        "DCACHE_TLB_PTE1_SELECT",
74        "DCACHE_TLB_PTE1_UPDT",
75        "DCACHE_TLB_PTE2_GET",
76        "DCACHE_TLB_PTE2_SELECT",
77        "DCACHE_TLB_PTE2_UPDT",
78        "DCACHE_TLB_LR_UPDT",
79        "DCACHE_TLB_LR_WAIT",
80        "DCACHE_TLB_RETURN",
81
82        "DCACHE_XTN_SWITCH",
83        "DCACHE_XTN_SYNC",
84        "DCACHE_XTN_IC_INVAL_VA",
85        "DCACHE_XTN_IC_FLUSH",
86        "DCACHE_XTN_IC_INVAL_PA",
87        "DCACHE_XTN_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
1822        // Match between MISS address and CC address
1823        // note: In the same cycle we can handle a CLACK and a MISS match
1824        // because the CLACK access the directory but the MISS match dont.
1825        if (r_cc_receive_icache_req.read() and
1826          ((r_icache_fsm_save.read() == ICACHE_MISS_SELECT  )  or
1827           (r_icache_fsm_save.read() == ICACHE_MISS_WAIT    )  or
1828           (r_icache_fsm_save.read() == ICACHE_MISS_DIR_UPDT)) and
1829          ((r_icache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching
1830        {
1831            // signaling the matching
1832            r_icache_miss_inval     = true;
1833
1834            // in case of update, go to CC_UPDT
1835            // JUST TO POP THE FIFO
1836            if (r_cc_receive_icache_type.read() == CC_TYPE_UPDT)
1837            {
1838                r_icache_fsm        = ICACHE_CC_UPDT;
1839                r_icache_cc_word    = r_cc_receive_word_idx.read();
1840
1841                // just pop the fifo , don't write in icache
1842                r_icache_cc_need_write = false;
1843            }
1844            // the request is dealt with
1845            else
1846            {
1847                r_cc_receive_icache_req = false;
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> Coherence request matching a pending miss:"
1855              << " PADDR = " << std::hex << paddr << std::endl;
1856}
1857#endif
1858        }
1859
1860        // CLACK handler
1861        // We switch the directory slot to EMPTY state
1862        // and reset r_icache_miss_clack if the cleanup ack
1863        // is matching a pending miss.
1864        if ( r_icache_clack_req.read() )
1865        {
1866
1867            if ( m_ireq.valid ) m_cost_ins_miss_frz++;
1868
1869#ifdef INSTRUMENTATION
1870m_cpt_icache_dir_write++;
1871#endif
1872            r_icache.write_dir( 0,
1873                                r_icache_clack_way.read(),
1874                                r_icache_clack_set.read(),
1875                                CACHE_SLOT_STATE_EMPTY);
1876
1877            if ( (r_icache_miss_set.read() == r_icache_clack_set.read()) and
1878                 (r_icache_miss_way.read() == r_icache_clack_way.read()) )
1879            {
1880                r_icache_miss_clack = false;
1881            }
1882
1883            r_icache_clack_req = false;
1884
1885            // return to cc_save state if no pending CC request
1886            if ( not r_cc_receive_icache_req.read() )
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>  CC_TYPE_CLACK slot returns to empty state"
1894        << " set = " << r_icache_clack_set.read()
1895        << " / way = " << r_icache_clack_way.read() << std::endl;
1896}
1897#endif
1898
1899            break;
1900        }
1901
1902        // CC request handler
1903
1904        int             state = 0;
1905        size_t      way = 0;
1906        size_t      set = 0;
1907        size_t      word = 0;
1908
1909#ifdef INSTRUMENTATION
1910m_cpt_icache_dir_read++;
1911#endif
1912        r_icache.read_dir(paddr,
1913                          &state,
1914                          &way,
1915                          &set,
1916                          &word);
1917
1918        r_icache_cc_way = way;
1919        r_icache_cc_set = set;
1920
1921        if ( state == CACHE_SLOT_STATE_VALID)            // hit
1922        {
1923            // need to update the cache state
1924            if (r_cc_receive_icache_type.read() == CC_TYPE_UPDT)  // hit update
1925            {
1926                r_icache_cc_need_write = true;
1927                r_icache_fsm           = ICACHE_CC_UPDT;
1928                r_icache_cc_word       = r_cc_receive_word_idx.read();
1929            }
1930            else if ( r_cc_receive_icache_type.read() == CC_TYPE_INVAL ) // hit inval
1931            {
1932                r_icache_fsm           = ICACHE_CC_INVAL;
1933            }
1934        }
1935        else                                      // miss
1936        {
1937            // multicast acknowledgement required in case of update
1938            if(r_cc_receive_icache_type.read() == CC_TYPE_UPDT)
1939            {
1940                r_icache_fsm           = ICACHE_CC_UPDT;
1941                r_icache_cc_word       = r_cc_receive_word_idx.read();
1942
1943                // just pop the fifo , don't write in icache
1944                r_icache_cc_need_write = false;
1945            }
1946            else // No response needed
1947            {
1948                r_cc_receive_icache_req = false;
1949                r_icache_fsm            = r_icache_fsm_save.read();
1950            }
1951        }
1952        break;
1953    }
1954    /////////////////////
1955    case ICACHE_CC_INVAL:       // hit inval : switch slot to ZOMBI state
1956    {
1957        // return to CC_CHECK if pending request to CC_SEND
1958        // to handle possible pending CLACK and avoid deadlock
1959        if (r_icache_cc_send_req.read())
1960        {
1961            r_icache_fsm = ICACHE_CC_CHECK;
1962            break; 
1963        } 
1964
1965#ifdef INSTRUMENTATION
1966m_cpt_icache_dir_read++;
1967#endif
1968
1969        // Switch slot state to ZOMBI and send CLEANUP command
1970        r_icache.write_dir( 0,
1971                            r_icache_cc_way.read(),
1972                            r_icache_cc_set.read(),
1973                            CACHE_SLOT_STATE_ZOMBI );
1974
1975        // coherence request completed
1976        r_icache_cc_send_req   = true;
1977        r_icache_cc_send_nline = r_cc_receive_icache_nline.read();
1978        r_icache_cc_send_way   = r_icache_cc_way.read();
1979        r_icache_cc_send_type  = CC_TYPE_CLEANUP;
1980
1981        r_icache_fsm           = r_icache_fsm_save.read();
1982
1983#if DEBUG_ICACHE
1984if ( m_debug_activated )
1985{
1986std::cout << "  <PROC " << name()
1987          << " ICACHE_CC_INVAL> slot returns to ZOMBI state"
1988          << " set = " << r_icache_cc_set.read()
1989          << " / way = " << r_icache_cc_way.read() << std::endl;
1990}
1991#endif
1992
1993        break;
1994    }
1995    ////////////////////
1996    case ICACHE_CC_UPDT:        // hit update : write one word per cycle
1997    {
1998
1999        // if pending request to CC_SEND or if the CC_UPDT data is not ready to
2000        // handle possible pending CLACK and avoid deadlock
2001        if ( r_icache_cc_send_req.read() )
2002        {
2003            r_icache_fsm = ICACHE_CC_CHECK;
2004            break;
2005        }
2006
2007        if ( not r_cc_receive_updt_fifo_be.rok() ) break;
2008
2009
2010        size_t  word  = r_icache_cc_word.read();
2011        size_t  way   = r_icache_cc_way.read();
2012        size_t  set   = r_icache_cc_set.read();
2013
2014        if (r_icache_cc_need_write.read())
2015        {
2016            r_icache.write( way,
2017                            set,
2018                            word,
2019                            r_cc_receive_updt_fifo_data.read(),
2020                            r_cc_receive_updt_fifo_be.read() );
2021
2022            r_icache_cc_word = word+1;
2023
2024#ifdef INSTRUMENTATION
2025m_cpt_icache_data_write++;
2026#endif
2027
2028#if DEBUG_ICACHE
2029if ( m_debug_activated )
2030{
2031    std::cout << "  <PROC " << name()
2032              << " ICACHE_CC_UPDT> Write one word "
2033              << " set = " << r_icache_cc_set.read()
2034              << " / way = " << r_icache_cc_way.read()
2035              << " / word = " << r_icache_cc_word.read() << std::endl;
2036}
2037#endif
2038        }
2039
2040        if ( r_cc_receive_updt_fifo_eop.read() )        // last word
2041        {
2042            // no need to write in the cache anymore
2043            r_icache_cc_need_write        = false;
2044
2045            // coherence request completed
2046            r_cc_receive_icache_req       = false;
2047
2048            // request multicast acknowledgement
2049            r_icache_cc_send_req          = true;
2050            r_icache_cc_send_nline        = r_cc_receive_icache_nline.read();
2051            r_icache_cc_send_updt_tab_idx = r_cc_receive_icache_updt_tab_idx.read();
2052            r_icache_cc_send_type         = CC_TYPE_MULTI_ACK;
2053
2054            r_icache_fsm                  = r_icache_fsm_save.read();
2055        }
2056        //consume fifo if not eop
2057        cc_receive_updt_fifo_get  = true;
2058
2059        break;
2060    }
2061
2062    } // end switch r_icache_fsm
2063
2064    ////////////////////////////////////////////////////////////////////////////////////
2065    //      DCACHE FSM
2066    //
2067    // 1/ Coherence operations
2068    //    They are handled as interrupts generated by the CC_RECEIVE FSM.
2069    //    - There is a coherence request when r_tgt_dcache_req is set.
2070    //    They are taken in IDLE, MISS_WAIT, MISS_DIR_UPDT, UNC_WAIT, LL_WAIT
2071    //    and SC_WAIT states.
2072    //    - There is a cleanup acknowledge request when r_cleanup_dcache_req is set.
2073    //    They are taken in IDLE, MISS_SELECT, MISS_CLEAN, MISS_WAIT, MISS_DATA_UPDT,
2074    //    MISS_DIR_UPDT, UNC_WAIT, LL_WAIT, SC_WAIT states.
2075    //    - For both types of requests, actions associated to the pre-empted state
2076    //    are not executed. The DCACHE FSM goes to the proper sub-FSM (CC_CHECK
2077    //    or CC_CLACK) to execute the requested coherence operation, and returns
2078    //    to the pre-empted state.
2079    //
2080    // 2/ TLB miss
2081    //    The page tables are generally cacheable.
2082    //    In case of miss in itlb or dtlb, the tlb miss is handled by a dedicated
2083    //    sub-fsm (DCACHE_TLB_MISS state), that handle possible miss in DCACHE,
2084    //    this sub-fsm implement the table-walk...
2085    //
2086    // 3/ processor requests
2087    //    Processor requests are taken in IDLE state only.
2088    //    The IDLE state implements a two stages pipe-line to handle write bursts:
2089    //    - Both DTLB and DCACHE are accessed in stage P0 (if processor request valid).
2090    //    - The registration in wbuf and the dcache update is done in stage P1
2091    //      (if the processor request is a write).
2092    //    The two r_dcache_wbuf_req and r_dcache_updt_req flip-flops define
2093    //    the operations that must be done in P1 stage, and the access type
2094    //    (read or write) to the DATA part of DCACHE depends on r_dcache_updt_req.
2095    //    READ requests are delayed if a cache update is requested.
2096    //    WRITE or SC requests can require a PTE Dirty bit update (in memory),
2097    //    that is done (before handling the processor request) by a dedicated sub-fsm.
2098    //    If a PTE is modified, both the itlb and dtlb are selectively, but sequencially
2099    //    cleared by a dedicated sub_fsm (DCACHE_INVAL_TLB_SCAN state).
2100    //
2101    // 4/ Atomic instructions LL/SC
2102    //    The LL/SC address are non cacheable (systematic access to memory).
2103    //    The llsc buffer contains a registration for an active LL/SC operation
2104    //    (with an address, a registration key, an aging counter and a valid bit).
2105    //    - LL requests from the processor are transmitted as a one flit VCI command
2106    //      (CMD_LOCKED_READ as CMD, and TYPE_LL as PKTID value). PLEN must
2107    //      be 8 as the response is 2 flits long (data and registration key)
2108    //    - SC requests from the processor are systematically transmitted to the
2109    //      memory cache as 2 flits VCI command (CMD_STORE_COND as CMD, and TYPE_SC
2110    //      as PKTID value).  The first flit contains the registration key, the second
2111    //      flit contains the data to write in case of success.
2112    //      The cache is not updated, as this is done in case of success by the
2113    //      coherence transaction.
2114    //
2115    // 5/ Non cacheable access:
2116    //    This component implement a strong order between non cacheable access
2117    //    (read or write) : A new non cacheable VCI transaction starts only when
2118    //    the previous non cacheable transaction is completed. Both cacheable and
2119    //    non cacheable transactions use the write buffer, but the DCACHE FSM registers
2120    //    a non cacheable write transaction posted in the write buffer by setting the
2121    //    r_dcache_pending_unc_write flip_flop. All other non cacheable requests
2122    //    are stalled until this flip-flop is reset by the VCI_RSP_FSM (when the
2123    //    pending non cacheable write transaction completes).
2124    //
2125    // 6/ Error handling:
2126    //    When the MMU is not activated, Read Bus Errors are synchronous events,
2127    //    but Write Bus Errors are asynchronous events (processor is not frozen).
2128    //    - If a Read Bus Error is detected, the VCI_RSP FSM sets the
2129    //      r_vci_rsp_data_error flip-flop, without writing any data in the
2130    //      r_vci_rsp_fifo_dcache FIFO, and the synchronous error is signaled
2131    //      by the DCACHE FSM.
2132    //    - If a Write Bus Error is detected, the VCI_RSP FSM  signals
2133    //      the asynchronous error using the setWriteBerr() method.
2134    //    When the MMU is activated bus error are rare events, as the MMU
2135    //    checks the physical address before the VCI transaction starts.
2136    ////////////////////////////////////////////////////////////////////////////////////////
2137
2138    // default value for m_drsp
2139    m_drsp.valid = false;
2140    m_drsp.error = false;
2141    m_drsp.rdata = 0;
2142
2143    switch ( r_dcache_fsm.read() )
2144    {
2145    case DCACHE_IDLE: // There are 10 conditions to exit the IDLE state :
2146                      // 1) ITLB/DTLB inval request (update)  => DCACHE_INVAL_TLB_SCAN
2147                      // 2) Coherence request (TGT FSM)       => DCACHE_CC_CHECK
2148                      // 3) ITLB miss request (ICACHE FSM)    => DCACHE_TLB_MISS
2149                      // 4) XTN request (processor)           => DCACHE_XTN_*
2150                      // 5) DTLB miss (processor)             => DCACHE_TLB_MISS
2151                      // 6) Dirty bit update (processor)      => DCACHE_DIRTY_GET_PTE
2152                      // 7) Cacheable read miss (processor)   => DCACHE_MISS_SELECT
2153                      // 8) Uncacheable read (processor)      => DCACHE_UNC_WAIT
2154                      // 9) LL access (processor)             => DCACHE_LL_WAIT
2155                      // 10) SC access (processor)            => DCACHE_SC_WAIT
2156                      //
2157                      // There is a fixed priority to handle requests to DCACHE:
2158                      //    1/ the ITLB/DTLB invalidate requests
2159                      //    2/ the coherence requests,
2160                      //    3/ the processor requests (including DTLB miss),
2161                      //    4/ the ITLB miss requests,
2162                      // The address space processor request are handled as follows:
2163                      // - WRITE request is blocked if the Dirty bit mus be set.
2164                      // If DTLB hit, the P1 stage is activated (writes WBUF, and
2165                      // updates DCACHE if DCACHE hit) & processor request acknowledged.
2166                      // - READ request generate a simultaneouss access to  DCACHE.DATA
2167                      // and DCACHE.DIR, but is delayed if DCACHE update required.
2168                      //
2169                      // There is 4 configurations defining the access type to
2170                      // DTLB, DCACHE.DATA, and DCACHE.DIR, depending on the
2171                      // dreq.valid (dreq) and r_dcache_updt_req (updt) signals:
2172                      //    dreq / updt / DTLB  / DCACHE.DIR / DCACHE.DATA /
2173                      //     0   /  0   / NOP   / NOP        / NOP         /
2174                      //     0   /  1   / NOP   / NOP        / WRITE       /
2175                      //     1   /  0   / READ  / READ       / NOP         /
2176                      //     1   /  1   / READ  / READ       / WRITE       /
2177                      // Those two registers are set at each cycle from the 3 signals
2178                      // updt_request, wbuf_request, wbuf_write_miss.
2179    {
2180        paddr_t     paddr;                          // physical address
2181        pte_info_t      tlb_flags;
2182        size_t          tlb_way;
2183        size_t          tlb_set;
2184        paddr_t         tlb_nline = 0;
2185        size_t          cache_way;
2186        size_t          cache_set;
2187        size_t          cache_word;
2188        uint32_t        cache_rdata = 0;
2189        bool        tlb_hit = false;
2190        int             cache_state = CACHE_SLOT_STATE_EMPTY;
2191
2192        bool        tlb_inval_required = false;     // request TLB inval after cache update
2193        bool        wbuf_write_miss    = false;     // miss a WBUF write request
2194        bool        updt_request       = false;     // request DCACHE update in P1 stage
2195        bool        wbuf_request       = false;     // request WBUF write in P1 stage
2196
2197        // physical address computation : systematic DTLB access if activated)
2198        if ( m_dreq.valid )
2199        {
2200            if ( r_mmu_mode.read() & DATA_TLB_MASK )  // DTLB activated
2201            {
2202                tlb_hit = r_dtlb.translate( m_dreq.addr,
2203                                            &paddr,
2204                                            &tlb_flags,
2205                                            &tlb_nline,
2206                                            &tlb_way,
2207                                            &tlb_set );
2208#ifdef INSTRUMENTATION
2209m_cpt_dtlb_read++;
2210#endif
2211            }
2212            else                                    // identity mapping
2213            {
2214                paddr = (paddr_t)m_dreq.addr;
2215                // we take into account the paddr extension
2216                if (vci_param::N > 32) 
2217                    paddr = paddr | ((paddr_t)(r_dcache_paddr_ext.read()) << 32);
2218            }
2219        } // end physical address computation
2220
2221        // systematic DCACHE access depending on r_dcache_updt_req (if activated)
2222        if ( r_mmu_mode.read() & DATA_CACHE_MASK)
2223        {
2224            if ( m_dreq.valid and r_dcache_updt_req.read() ) // read DIR and write DATA
2225            {
2226                r_dcache.read_dir( paddr,
2227                                   &cache_state,
2228                                   &cache_way,
2229                                   &cache_set,
2230                                   &cache_word );
2231
2232                r_dcache.write( r_dcache_save_cache_way.read(),
2233                                r_dcache_save_cache_set.read(),
2234                                r_dcache_save_cache_word.read(),
2235                                r_dcache_save_wdata.read(),
2236                                r_dcache_save_be.read() );
2237#ifdef INSTRUMENTATION
2238m_cpt_dcache_dir_read++;
2239m_cpt_dcache_data_write++;
2240#endif
2241            }
2242            else if ( m_dreq.valid and not r_dcache_updt_req.read() ) // read DIR and DATA
2243            {
2244                r_dcache.read( paddr,
2245                               &cache_rdata,
2246                               &cache_way,
2247                               &cache_set,
2248                               &cache_word,
2249                               &cache_state );
2250
2251#ifdef INSTRUMENTATION
2252m_cpt_dcache_dir_read++;
2253m_cpt_dcache_data_read++;
2254#endif
2255            }
2256            else if ( not m_dreq.valid and r_dcache_updt_req.read() ) // write DATA
2257            {
2258                r_dcache.write( r_dcache_save_cache_way.read(),
2259                                r_dcache_save_cache_set.read(),
2260                                r_dcache_save_cache_word.read(),
2261                                r_dcache_save_wdata.read(),
2262                                r_dcache_save_be.read() );
2263#ifdef INSTRUMENTATION
2264m_cpt_dcache_data_write++;
2265#endif
2266            }
2267        } // end dcache access
2268
2269        // DCACHE update in P1 stage can require ITLB / DTLB inval or flush
2270        if ( r_dcache_updt_req.read() )
2271        {
2272            size_t way = r_dcache_save_cache_way.read();
2273            size_t set = r_dcache_save_cache_set.read();
2274
2275            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
2276            {
2277                tlb_inval_required       = true;
2278                    r_dcache_tlb_inval_set   = 0;
2279                    r_dcache_tlb_inval_line  = r_dcache_save_paddr.read()>>
2280                                           (uint32_log2(m_dcache_words<<2));
2281                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
2282            }
2283            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
2284            {
2285                r_itlb.reset();
2286                r_dtlb.reset();
2287                    r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
2288            }
2289
2290#if DEBUG_DCACHE
2291if ( m_debug_activated )
2292std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2293          << " Cache update in P1 stage" << std::dec
2294          << " / WAY = " << r_dcache_save_cache_way.read()
2295          << " / SET = " << r_dcache_save_cache_set.read()
2296          << " / WORD = " << r_dcache_save_cache_word.read() << std::hex
2297          << " / WDATA = " << r_dcache_save_wdata.read()
2298          << " / BE = " << r_dcache_save_be.read() << std::endl;
2299#endif
2300        } // end test TLB inval
2301
2302        // Try WBUF update in P1 stage
2303        // Miss if the write request is non cacheable, and there is a pending
2304        // non cacheable write, or if the write buffer is full.
2305        if ( r_dcache_wbuf_req.read() )
2306        {
2307            // miss if write not cacheable, and previous non cacheable write registered
2308            if ( not r_dcache_save_cacheable.read() and r_dcache_pending_unc_write.read() )
2309            {
2310                wbuf_write_miss = true;
2311            }
2312            else                // try a registration into write buffer
2313            {
2314                bool wok = r_wbuf.write( r_dcache_save_paddr.read(),
2315                                         r_dcache_save_be.read(),
2316                                         r_dcache_save_wdata.read(),
2317                                         r_dcache_save_cacheable.read() );
2318#ifdef INSTRUMENTATION
2319m_cpt_wbuf_write++;
2320#endif
2321                if ( not wok ) // miss if write buffer full
2322                {
2323                    wbuf_write_miss = true;
2324                }
2325                else          // update the write_buffer state extension
2326                {
2327                    if(not r_dcache_pending_unc_write.read())
2328                        r_dcache_pending_unc_write = not r_dcache_save_cacheable.read();
2329                }
2330            }
2331        } // end WBUF update
2332
2333        // Computing the response to processor,
2334        // and the next value for r_dcache_fsm
2335
2336        // itlb/dtlb invalidation self-request
2337        if ( tlb_inval_required )
2338        {
2339            r_dcache_fsm_scan_save = r_dcache_fsm.read();
2340            r_dcache_fsm           = DCACHE_INVAL_TLB_SCAN;
2341        }
2342
2343        // coherence clack request (from DSPIN CLACK)
2344        else if ( r_dcache_clack_req.read() )
2345        {
2346            r_dcache_fsm = DCACHE_CC_CHECK;
2347            r_dcache_fsm_cc_save = r_dcache_fsm.read();
2348        }
2349        // coherence request (from CC_RECEIVE FSM)
2350        else if ( r_cc_receive_dcache_req.read() )
2351        {
2352            r_dcache_fsm = DCACHE_CC_CHECK;
2353            r_dcache_fsm_cc_save = r_dcache_fsm.read();
2354        }
2355
2356        // processor request (READ, WRITE, LL, SC, XTN_READ, XTN_WRITE)
2357        // we don't take the processor request, and registers
2358        // are frozen in case of wbuf_write_miss
2359        else if ( m_dreq.valid and not wbuf_write_miss )
2360        {
2361            // register processor request and DCACHE response
2362            r_dcache_save_vaddr      = m_dreq.addr;
2363            r_dcache_save_be         = m_dreq.be;
2364            r_dcache_save_wdata      = m_dreq.wdata;
2365            r_dcache_save_paddr      = paddr;
2366            r_dcache_save_cache_way  = cache_way;
2367            r_dcache_save_cache_set  = cache_set;
2368            r_dcache_save_cache_word = cache_word;
2369
2370            // READ XTN requests from processor
2371            // They are executed in this DCACHE_IDLE state.
2372            // The processor must not be in user mode
2373            if (m_dreq.type == iss_t::XTN_READ)
2374            {
2375                int xtn_opcode = (int)m_dreq.addr/4;
2376
2377                // checking processor mode:
2378                if (m_dreq.mode  == iss_t::MODE_USER)
2379                {
2380                    r_mmu_detr   = MMU_READ_PRIVILEGE_VIOLATION;
2381                    r_mmu_dbvar  = m_dreq.addr;
2382                    m_drsp.valid = true;
2383                    m_drsp.error = true;
2384                    m_drsp.rdata = 0;
2385                    r_dcache_fsm = DCACHE_IDLE;
2386                }
2387                else
2388                {
2389                    switch( xtn_opcode )
2390                    {
2391                    case iss_t::XTN_INS_ERROR_TYPE:
2392                        m_drsp.rdata = r_mmu_ietr.read();
2393                        m_drsp.valid = true;
2394                        m_drsp.error = false;
2395                        break;
2396
2397                    case iss_t::XTN_DATA_ERROR_TYPE:
2398                        m_drsp.rdata = r_mmu_detr.read();
2399                        m_drsp.valid = true;
2400                        m_drsp.error = false;
2401                        break;
2402
2403                    case iss_t::XTN_INS_BAD_VADDR:
2404                        m_drsp.rdata = r_mmu_ibvar.read();
2405                        m_drsp.valid = true;
2406                        m_drsp.error = false;
2407                        break;
2408
2409                    case iss_t::XTN_DATA_BAD_VADDR:
2410                        m_drsp.rdata = r_mmu_dbvar.read();
2411                        m_drsp.valid = true;
2412                        m_drsp.error = false;
2413                        break;
2414
2415                    case iss_t::XTN_PTPR:
2416                        m_drsp.rdata = r_mmu_ptpr.read();
2417                        m_drsp.valid = true;
2418                        m_drsp.error = false;
2419                        break;
2420
2421                    case iss_t::XTN_TLB_MODE:
2422                        m_drsp.rdata = r_mmu_mode.read();
2423                        m_drsp.valid = true;
2424                        m_drsp.error = false;
2425                        break;
2426
2427                    case iss_t::XTN_MMU_PARAMS:
2428                        m_drsp.rdata = r_mmu_params;
2429                        m_drsp.valid = true;
2430                        m_drsp.error = false;
2431                        break;
2432
2433                    case iss_t::XTN_MMU_RELEASE:
2434                        m_drsp.rdata = r_mmu_release;
2435                        m_drsp.valid = true;
2436                        m_drsp.error = false;
2437                        break;
2438
2439                    case iss_t::XTN_MMU_WORD_LO:
2440                        m_drsp.rdata = r_mmu_word_lo.read();
2441                        m_drsp.valid = true;
2442                        m_drsp.error = false;
2443                        break;
2444
2445                    case iss_t::XTN_MMU_WORD_HI:
2446                        m_drsp.rdata = r_mmu_word_hi.read();
2447                        m_drsp.valid = true;
2448                        m_drsp.error = false;
2449                        break;
2450
2451                    case iss_t::XTN_DATA_PADDR_EXT:
2452                        m_drsp.rdata = r_dcache_paddr_ext.read();
2453                        m_drsp.valid = true;
2454                        m_drsp.error = false;
2455                        break;
2456
2457                    default:
2458                        r_mmu_detr = MMU_READ_UNDEFINED_XTN;
2459                        r_mmu_dbvar  = m_dreq.addr;
2460                        m_drsp.valid = true;
2461                        m_drsp.error = true;
2462                        m_drsp.rdata = 0;
2463                        break;
2464                    } // end switch xtn_opcode
2465                } // end else
2466            } // end if XTN_READ
2467
2468            // Handling WRITE XTN requests from processor.
2469            // They are not executed in this DCACHE_IDLE state
2470            // if they require access to the caches or the TLBs
2471            // that are already accessed.
2472            // Caches can be invalidated or flushed in user mode,
2473            // and the sync instruction can be executed in user mode
2474            else if (m_dreq.type == iss_t::XTN_WRITE)
2475            {
2476                int xtn_opcode      = (int)m_dreq.addr/4;
2477                r_dcache_xtn_opcode = xtn_opcode;
2478
2479                // checking processor mode:
2480                if ( (m_dreq.mode  == iss_t::MODE_USER) &&
2481                     (xtn_opcode != iss_t::XTN_SYNC) &&
2482                     (xtn_opcode != iss_t::XTN_DCACHE_INVAL) &&
2483                     (xtn_opcode != iss_t::XTN_DCACHE_FLUSH) &&
2484                     (xtn_opcode != iss_t::XTN_ICACHE_INVAL) &&
2485                     (xtn_opcode != iss_t::XTN_ICACHE_FLUSH) )
2486                {
2487                    r_mmu_detr   = MMU_WRITE_PRIVILEGE_VIOLATION;
2488                    r_mmu_dbvar  = m_dreq.addr;
2489                    m_drsp.valid = true;
2490                    m_drsp.error = true;
2491                    m_drsp.rdata = 0;
2492                    r_dcache_fsm = DCACHE_IDLE;
2493                }
2494                else
2495                {
2496                    switch( xtn_opcode )
2497                    {
2498                    case iss_t::XTN_PTPR:                       // itlb & dtlb must be flushed
2499                        r_dcache_xtn_req = true;
2500                        r_dcache_fsm     = DCACHE_XTN_SWITCH;
2501                        break;
2502
2503                    case iss_t::XTN_TLB_MODE:                   // no cache or tlb access
2504                        r_mmu_mode       = m_dreq.wdata;
2505                        m_drsp.valid     = true;
2506                        r_dcache_fsm     = DCACHE_IDLE;
2507                        break;
2508
2509                    case iss_t::XTN_DTLB_INVAL:                 // dtlb access
2510                        r_dcache_fsm     = DCACHE_XTN_DT_INVAL;
2511                        break;
2512
2513                    case iss_t::XTN_ITLB_INVAL:                 // itlb access
2514                        r_dcache_xtn_req = true;
2515                        r_dcache_fsm     = DCACHE_XTN_IT_INVAL;
2516                        break;
2517
2518                    case iss_t::XTN_DCACHE_INVAL:               // dcache, dtlb & itlb access
2519                        r_dcache_fsm     = DCACHE_XTN_DC_INVAL_VA;
2520                        break;
2521
2522                    case iss_t::XTN_MMU_DCACHE_PA_INV:          // dcache, dtlb & itlb access
2523                        r_dcache_fsm     = DCACHE_XTN_DC_INVAL_PA;
2524                        if (sizeof(paddr_t) <= 32)
2525                        {
2526                            assert(r_mmu_word_hi.read() == 0 &&
2527                            "high bits should be 0 for 32bit paddr");
2528                            r_dcache_save_paddr = (paddr_t)r_mmu_word_lo.read();
2529                        }
2530                        else
2531                        {
2532                            r_dcache_save_paddr = (paddr_t)r_mmu_word_hi.read() << 32 |
2533                                                  (paddr_t)r_mmu_word_lo.read();
2534                        }
2535                        break;
2536
2537                    case iss_t::XTN_DCACHE_FLUSH:              // itlb and dtlb must be reset
2538                        r_dcache_flush_count = 0;
2539                        r_dcache_fsm     = DCACHE_XTN_DC_FLUSH;
2540                        break;
2541
2542                    case iss_t::XTN_ICACHE_INVAL:               // icache and itlb access
2543                        r_dcache_xtn_req = true;
2544                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_VA;
2545                        break;
2546
2547                    case iss_t::XTN_MMU_ICACHE_PA_INV:          // icache access
2548                        r_dcache_xtn_req = true;
2549                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_PA;
2550                        break;
2551
2552                    case iss_t::XTN_ICACHE_FLUSH:               // icache access
2553                        r_dcache_xtn_req = true;
2554                        r_dcache_fsm     = DCACHE_XTN_IC_FLUSH;
2555                        break;
2556
2557                    case iss_t::XTN_SYNC:                       // wait until write buffer empty
2558                        r_dcache_fsm     = DCACHE_XTN_SYNC;
2559                        break;
2560
2561                    case iss_t::XTN_MMU_WORD_LO:                // no cache or tlb access
2562                        r_mmu_word_lo    = m_dreq.wdata;
2563                        m_drsp.valid     = true;
2564                        r_dcache_fsm     = DCACHE_IDLE;
2565                        break;
2566
2567                    case iss_t::XTN_MMU_WORD_HI:                // no cache or tlb access
2568                        r_mmu_word_hi    = m_dreq.wdata;
2569                        m_drsp.valid     = true;
2570                        r_dcache_fsm     = DCACHE_IDLE;
2571                        break;
2572
2573                    case iss_t::XTN_MMU_LL_RESET:      // no cache or tlb access
2574                        r_dcache_llsc_valid = false;
2575                        m_drsp.valid     = true;
2576                        r_dcache_fsm     = DCACHE_IDLE;
2577                    break;
2578
2579                    case iss_t::XTN_DATA_PADDR_EXT:     // no cache or tlb access
2580                        r_dcache_paddr_ext = m_dreq.wdata;
2581                        m_drsp.valid       = true;
2582                        r_dcache_fsm       = DCACHE_IDLE;
2583                    break;
2584
2585                        case iss_t::XTN_ICACHE_PREFETCH:                // not implemented : no action
2586                        case iss_t::XTN_DCACHE_PREFETCH:                // not implemented : no action
2587                        m_drsp.valid     = true;
2588                        r_dcache_fsm     = DCACHE_IDLE;
2589                            break;
2590
2591                    default:
2592                        r_mmu_detr   = MMU_WRITE_UNDEFINED_XTN;
2593                        r_mmu_dbvar  = m_dreq.addr;
2594                        m_drsp.valid = true;
2595                        m_drsp.error = true;
2596                        r_dcache_fsm = DCACHE_IDLE;
2597                        break;
2598                    } // end switch xtn_opcode
2599                } // end else
2600            } // end if XTN_WRITE
2601
2602            // Handling processor requests to address space (READ/WRITE/LL/SC)
2603            // The dtlb and dcache can be activated or not.
2604            // We compute the cacheability, and check processor request validity:
2605            // - If DTLB not activated : cacheability is defined by the segment table,
2606            //   and there is no access rights checking.
2607            // - If DTLB activated : cacheability is defined by the C bit in the PTE,
2608            //   and the U & W bits of the PTE are checked, as well as the DTLB hit.
2609            //   Jumps to the TLB_MISS sub-fsm in case of dtlb miss.
2610            else
2611            {
2612                bool        valid_req;
2613                bool        cacheable;
2614
2615                if ( not (r_mmu_mode.read() & DATA_TLB_MASK) )          // dtlb not activated
2616                {
2617                    valid_req     = true;
2618
2619                    if ( not (r_mmu_mode.read() & DATA_CACHE_MASK) ) cacheable = false;
2620                    else cacheable = m_cacheability_table[m_dreq.addr];
2621                }
2622                else                                                                       // dtlb activated
2623                {
2624                    if ( tlb_hit )                                      // tlb hit
2625                    {
2626                        // cacheability
2627                        if ( not (r_mmu_mode.read() & DATA_CACHE_MASK) ) cacheable = false;
2628                        else cacheable = tlb_flags.c;
2629
2630                        // access rights checking
2631                        if ( not tlb_flags.u and (m_dreq.mode == iss_t::MODE_USER))
2632                        {
2633                            if ( (m_dreq.type == iss_t::DATA_READ) or
2634                                 (m_dreq.type == iss_t::DATA_LL) )
2635                            {
2636                                r_mmu_detr = MMU_READ_PRIVILEGE_VIOLATION;
2637                            }
2638                            else
2639                            {
2640                                r_mmu_detr = MMU_WRITE_PRIVILEGE_VIOLATION;
2641                            }
2642                            valid_req    = false;
2643                            r_mmu_dbvar  = m_dreq.addr;
2644                            m_drsp.valid = true;
2645                            m_drsp.error = true;
2646                            m_drsp.rdata = 0;
2647#if DEBUG_DCACHE
2648if ( m_debug_activated )
2649std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2650          << " HIT in dtlb, but privilege violation" << std::endl;
2651#endif
2652                        }
2653                        else if ( not tlb_flags.w and
2654                                  ((m_dreq.type == iss_t::DATA_WRITE) or
2655                                   (m_dreq.type == iss_t::DATA_SC)) )
2656                        {
2657                            r_mmu_detr   = MMU_WRITE_ACCES_VIOLATION;
2658                            valid_req    = false;
2659                            r_mmu_dbvar  = m_dreq.addr;
2660                            m_drsp.valid = true;
2661                            m_drsp.error = true;
2662                            m_drsp.rdata = 0;
2663#if DEBUG_DCACHE
2664if ( m_debug_activated )
2665std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2666          << " HIT in dtlb, but writable violation" << std::endl;
2667#endif
2668                        }
2669                        else
2670                        {
2671                            valid_req    = true;
2672                        }
2673                    }
2674                    else                                                // tlb miss
2675                    {
2676                        valid_req            = false;
2677                        r_dcache_tlb_vaddr   = m_dreq.addr;
2678                        r_dcache_tlb_ins     = false;
2679                        r_dcache_fsm         = DCACHE_TLB_MISS;
2680                    }
2681                }    // end DTLB activated
2682
2683                if ( valid_req )        // processor request is valid (after MMU check)
2684                {
2685                    r_dcache_save_cacheable  = cacheable;
2686
2687                    // READ request
2688                    // The read requests are taken only if there is no cache update.
2689                    // We request a VCI transaction to CMD FSM if miss or uncachable
2690
2691                    if ( ((m_dreq.type == iss_t::DATA_READ))
2692                          and not r_dcache_updt_req.read() )
2693                    {
2694                        if ( cacheable )                // cacheable read
2695                        {
2696                            if ( cache_state == CACHE_SLOT_STATE_EMPTY )   // cache miss
2697                            {
2698#ifdef INSTRUMENTATION
2699m_cpt_dcache_miss++;
2700#endif
2701                                // request a VCI DMISS transaction
2702                                r_dcache_vci_paddr    = paddr;
2703                                r_dcache_vci_miss_req = true;
2704                                r_dcache_miss_type    = PROC_MISS;
2705                                r_dcache_fsm          = DCACHE_MISS_SELECT;
2706#if DEBUG_DCACHE
2707if ( m_debug_activated )
2708std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2709          << " READ MISS in dcache" 
2710          << " / PADDR = " << std::hex << paddr << std::endl;
2711#endif
2712                            }
2713                            else if (cache_state == CACHE_SLOT_STATE_ZOMBI ) // pending cleanup
2714                            {
2715                                // stalled until cleanup is acknowledged
2716                                r_dcache_fsm   = DCACHE_IDLE;
2717#if DEBUG_DCACHE
2718if ( m_debug_activated )
2719std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2720          << " Pending cleanup, stalled until cleanup acknowledge"
2721          << " / PADDR = " << std::hex << paddr << std::endl;
2722#endif
2723                            }
2724                            else                                      // cache hit
2725                            {
2726#ifdef INSTRUMENTATION
2727m_cpt_data_read++;
2728#endif
2729                                // returns data to processor
2730                                m_drsp.valid   = true;
2731                                m_drsp.error   = false;
2732                                m_drsp.rdata   = cache_rdata;
2733#if DEBUG_DCACHE
2734if ( m_debug_activated )
2735std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2736          << " READ HIT in dcache" 
2737          << " / PADDR = " << std::hex << paddr << std::endl;
2738#endif
2739                            }
2740                        }
2741                        else                                    // uncacheable read
2742                        {
2743                            r_dcache_vci_paddr    = paddr;
2744                            r_dcache_vci_unc_be   = m_dreq.be;
2745                            r_dcache_vci_unc_req  = true;
2746                            r_dcache_fsm          = DCACHE_UNC_WAIT;
2747#if DEBUG_DCACHE
2748if ( m_debug_activated )
2749std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2750          << " READ UNCACHEABLE in dcache" 
2751          << " / PADDR = " << std::hex << paddr << std::endl;
2752#endif
2753                        }
2754                    } // end READ
2755
2756                    // LL request (non cachable)
2757                    // We request a VCI LL transaction to CMD FSM and register
2758                    // the LL/SC operation in llsc buffer.
2759                    else if (m_dreq.type == iss_t::DATA_LL)
2760                    {
2761                        // register paddr in LLSC buffer
2762                        r_dcache_llsc_paddr = paddr;
2763                        r_dcache_llsc_count = LLSC_TIMEOUT;
2764                        r_dcache_llsc_valid = true;
2765
2766                        // request an LL VCI transaction and go to DCACHE_LL_WAIT state
2767                        r_dcache_vci_ll_req   = true;
2768                        r_dcache_vci_paddr    = paddr;
2769                        r_dcache_ll_rsp_count = 0;
2770                        r_dcache_fsm          = DCACHE_LL_WAIT;
2771
2772                    }// end LL
2773
2774                    // WRITE request:
2775                    // If the TLB is activated and the PTE Dirty bit is not set, we stall
2776                    // the processor and set the Dirty bit before handling the write request,
2777                    // going to the DCACHE_DIRTY_GT_PTE state.
2778                    // If we don't need to set the Dirty bit, we can acknowledge
2779                    // the processor request, as the write arguments (including the
2780                    // physical address) are registered in r_dcache_save registers,
2781                    // and the write will be done in the P1 pipeline stage.
2782                    else if ( m_dreq.type == iss_t::DATA_WRITE )
2783                    {
2784                        if ( (r_mmu_mode.read() & DATA_TLB_MASK )
2785                              and not tlb_flags.d )             // Dirty bit must be set
2786                        {
2787                            // The PTE physical address is obtained from the nline value (dtlb),
2788                            // and from the virtual address (word index)
2789                            if ( tlb_flags.b )  // PTE1
2790                            {
2791                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2792                                                       (paddr_t)((m_dreq.addr>>19) & 0x3c);
2793                            }
2794                            else                // PTE2
2795                            {
2796                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2797                                                       (paddr_t)((m_dreq.addr>>9) & 0x38);
2798                            }
2799                            r_dcache_fsm      = DCACHE_DIRTY_GET_PTE;
2800                        }
2801                        else                                    // Write request accepted
2802                        {
2803#ifdef INSTRUMENTATION
2804m_cpt_data_write++;
2805#endif
2806                            // cleaning llsc buffer if address matching
2807                            if ( paddr == r_dcache_llsc_paddr.read() )
2808                                r_dcache_llsc_valid = false;
2809
2810                            // response to processor
2811                            m_drsp.valid        = true;
2812
2813                            // activating P1 stage
2814                            wbuf_request = true;
2815                            updt_request = (cache_state == CACHE_SLOT_STATE_VALID);
2816                        }
2817                    } // end WRITE
2818
2819                    // SC request:
2820                    // If the TLB is activated and the PTE Dirty bit is not set, we stall
2821                    // the processor and set the Dirty bit before handling the write request,
2822                    // going to the DCACHE_DIRTY_GT_PTE state.
2823                    // If we don't need to set the Dirty bit, we test the llsc buffer:
2824                    // If failure, we send a negative response to processor.
2825                    // If success, we request a SC transaction to CMD FSM and go
2826                    // to DCACHE_SC_WAIT state.
2827                    // We don't check a possible write hit in dcache, as the cache update
2828                    // is done by the coherence transaction induced by the SC...
2829                    else if ( m_dreq.type == iss_t::DATA_SC )
2830                    {
2831                        if ( (r_mmu_mode.read() & DATA_TLB_MASK )
2832                              and not tlb_flags.d )                     // Dirty bit must be set
2833                        {
2834                            // The PTE physical address is obtained from the nline value (dtlb),
2835                            // and the word index (virtual address)
2836                            if ( tlb_flags.b )  // PTE1
2837                            {
2838                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2839                                                       (paddr_t)((m_dreq.addr>>19) & 0x3c);
2840                            }
2841                            else                        // PTE2
2842                            {
2843                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2844                                                       (paddr_t)((m_dreq.addr>>9) & 0x38);
2845                            }
2846                            r_dcache_fsm           = DCACHE_DIRTY_GET_PTE;
2847                            m_drsp.valid = false;
2848                            m_drsp.error = false;
2849                            m_drsp.rdata = 0;
2850                        }
2851                        else                                    // SC request accepted
2852                        {
2853#ifdef INSTRUMENTATION
2854m_cpt_data_sc++;
2855#endif
2856                            // checking local success
2857                            if( r_dcache_llsc_valid.read() and
2858                                (r_dcache_llsc_paddr.read() == paddr) )  // local success
2859                            {
2860                                // request an SC CMD and go to DCACHE_SC_WAIT state
2861                                r_dcache_vci_paddr   = paddr;
2862                                r_dcache_vci_sc_req  = true;
2863                                r_dcache_vci_sc_data = m_dreq.wdata;
2864                                r_dcache_fsm         = DCACHE_SC_WAIT;
2865                            }
2866                            else                                          // local fail
2867                            {
2868                                    m_drsp.valid = true;
2869                                    m_drsp.error = false;
2870                                    m_drsp.rdata = 0x1;
2871                            }
2872                        }
2873                    } // end SC
2874                } // end valid_req
2875            }  // end if read/write/ll/sc request
2876        } // end processor request
2877
2878        // itlb miss request
2879        else if ( r_icache_tlb_miss_req.read() and not wbuf_write_miss )
2880        {
2881            r_dcache_tlb_ins    = true;
2882            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
2883            r_dcache_fsm        = DCACHE_TLB_MISS;
2884        }
2885
2886        // Computing requests for P1 stage : r_dcache_wbuf_req & r_dcache_updt_req
2887        r_dcache_updt_req = updt_request;
2888        r_dcache_wbuf_req = wbuf_request or
2889                            (r_dcache_wbuf_req.read() and wbuf_write_miss);
2890        break;
2891    }
2892    /////////////////////
2893    case DCACHE_TLB_MISS: // This is the entry point for the sub-fsm handling all tlb miss.
2894                          // Input arguments are:
2895                          // - r_dcache_tlb_vaddr
2896                          // - r_dcache_tlb_ins (true when itlb miss)
2897                          // The sub-fsm access the dcache to find the missing TLB entry,
2898                          // and activates the cache miss procedure in case of miss.
2899                          // It bypass the first level page table access if possible.
2900                          // It uses atomic access to update the R/L access bits
2901                          // in the page table if required.
2902                          // It directly updates the itlb or dtlb, and writes into the
2903                          // r_mmu_ins_* or r_mmu_data* error reporting registers.
2904    {
2905        uint32_t        ptba = 0;
2906        bool            bypass;
2907        paddr_t         pte_paddr;
2908
2909        // evaluate bypass in order to skip first level page table access
2910        if ( r_dcache_tlb_ins.read() )                          // itlb miss
2911        {
2912            bypass = r_itlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba);
2913        }
2914        else                                                    // dtlb miss
2915        {
2916            bypass = r_dtlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba);
2917        }
2918
2919        if ( not bypass )     // Try to read PTE1/PTD1 in dcache
2920        {
2921            pte_paddr = (((paddr_t)r_mmu_ptpr.read()) << (INDEX1_NBITS+2)) |
2922                        ((((paddr_t)r_dcache_tlb_vaddr.read()) >> PAGE_M_NBITS) << 2);
2923            r_dcache_tlb_paddr = pte_paddr;
2924            r_dcache_fsm       = DCACHE_TLB_PTE1_GET;
2925        }
2926        else                  // Try to read PTE2 in dcache
2927        {
2928            pte_paddr = (paddr_t)ptba << PAGE_K_NBITS |
2929                        (paddr_t)(r_dcache_tlb_vaddr.read()&PTD_ID2_MASK)>>(PAGE_K_NBITS-3);
2930            r_dcache_tlb_paddr = pte_paddr;
2931            r_dcache_fsm       = DCACHE_TLB_PTE2_GET;
2932        }
2933
2934#if DEBUG_DCACHE
2935if ( m_debug_activated )
2936{
2937    if ( r_dcache_tlb_ins.read() )
2938        std::cout << "  <PROC " << name() << " DCACHE_TLB_MISS> ITLB miss";
2939    else
2940        std::cout << "  <PROC " << name() << " DCACHE_TLB_MISS> DTLB miss";
2941    std::cout << " / VADDR = " << std::hex << r_dcache_tlb_vaddr.read()
2942              << " / ptpr  = " << (((paddr_t)r_mmu_ptpr.read()) << (INDEX1_NBITS+2))
2943              << " / BYPASS = " << bypass
2944              << " / PTE_ADR = " << pte_paddr << std::endl;
2945}
2946#endif
2947
2948        break;
2949    }
2950    /////////////////////////
2951    case DCACHE_TLB_PTE1_GET:   // try to read a PT1 entry in dcache
2952    {
2953        // coherence clack request (from DSPIN CLACK)
2954        if ( r_dcache_clack_req.read() )
2955        {
2956            r_dcache_fsm = DCACHE_CC_CHECK;
2957            r_dcache_fsm_cc_save = r_dcache_fsm.read();
2958            break;
2959        }
2960
2961        // coherence request (from CC_RECEIVE FSM)
2962        if ( r_cc_receive_dcache_req.read() )
2963        {
2964            r_dcache_fsm = DCACHE_CC_CHECK;
2965            r_dcache_fsm_cc_save = r_dcache_fsm.read();
2966            break;
2967        }
2968
2969        uint32_t        entry;
2970        size_t          way;
2971        size_t          set;
2972        size_t          word;
2973        int         cache_state;
2974        r_dcache.read( r_dcache_tlb_paddr.read(),
2975                       &entry,
2976                       &way,
2977                       &set,
2978                       &word,
2979                       &cache_state );
2980#ifdef INSTRUMENTATION
2981m_cpt_dcache_data_read++;
2982m_cpt_dcache_dir_read++;
2983#endif
2984        if ( cache_state == CACHE_SLOT_STATE_VALID )   // hit in dcache
2985        {
2986            if ( not (entry & PTE_V_MASK) )     // unmapped
2987            {
2988                if ( r_dcache_tlb_ins.read() )
2989                {
2990                    r_mmu_ietr             = MMU_READ_PT1_UNMAPPED;
2991                    r_mmu_ibvar            = r_dcache_tlb_vaddr.read();
2992                    r_icache_tlb_miss_req  = false;
2993                    r_icache_tlb_rsp_error = true;
2994                }
2995                else
2996                {
2997                    r_mmu_detr             = MMU_READ_PT1_UNMAPPED;
2998                    r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
2999                    m_drsp.valid             = true;
3000                    m_drsp.error             = true;
3001                }
3002                r_dcache_fsm          = DCACHE_IDLE;
3003
3004#if DEBUG_DCACHE
3005if ( m_debug_activated )
3006{
3007    std::cout << "  <PROC " << name() 
3008              << " DCACHE_TLB_PTE1_GET> HIT in dcache, but unmapped"
3009              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
3010              << std::dec << " / way = " << way
3011              << std::dec << " / set = " << set
3012              << std::dec << " / word = " << word
3013              << std::hex << " / PTE1 = " << entry << std::endl;
3014}
3015#endif
3016
3017            }
3018            else if( entry & PTE_T_MASK )       //  PTD : me must access PT2
3019            {
3020                // mark the cache line ac containing a PTD
3021                r_dcache_contains_ptd[m_dcache_sets*way+set] = true;
3022
3023                // register bypass
3024                if ( r_dcache_tlb_ins.read() )          // itlb
3025                {
3026                    r_itlb.set_bypass(r_dcache_tlb_vaddr.read(),
3027                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1),
3028                                      r_dcache_tlb_paddr.read() / (m_icache_words<<2) );
3029                }
3030                else                                    // dtlb
3031                {
3032                    r_dtlb.set_bypass(r_dcache_tlb_vaddr.read(),
3033                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1),
3034                                      r_dcache_tlb_paddr.read() / (m_dcache_words<<2) );
3035                }
3036                r_dcache_tlb_paddr =
3037                    (paddr_t)(entry & ((1<<(m_paddr_nbits-PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
3038                    (paddr_t)(((r_dcache_tlb_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
3039                r_dcache_fsm       = DCACHE_TLB_PTE2_GET;
3040
3041#if DEBUG_DCACHE
3042if ( m_debug_activated )
3043{
3044    std::cout << "  <PROC " << name() 
3045              << " DCACHE_TLB_PTE1_GET> HIT in dcache"
3046              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
3047              << std::dec << " / way = " << way
3048              << std::dec << " / set = " << set
3049              << std::dec << " / word = " << word
3050              << std::hex << " / PTD = " << entry << std::endl;
3051}
3052#endif
3053            }
3054            else                        //  PTE1 :  we must update the TLB
3055            {
3056                r_dcache_in_tlb[m_icache_sets*way+set] = true;
3057                r_dcache_tlb_pte_flags  = entry;
3058                r_dcache_tlb_cache_way  = way;
3059                r_dcache_tlb_cache_set  = set;
3060                r_dcache_tlb_cache_word = word;
3061                r_dcache_fsm            = DCACHE_TLB_PTE1_SELECT;
3062
3063#if DEBUG_DCACHE
3064if ( m_debug_activated )
3065{
3066    std::cout << "  <PROC " << name() 
3067              << " DCACHE_TLB_PTE1_GET> HIT in dcache"
3068              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
3069              << std::dec << " / way = " << way
3070              << std::dec << " / set = " << set
3071              << std::dec << " / word = " << word
3072              << std::hex << " / PTE1 = " << entry << std::endl;
3073}
3074#endif
3075            }
3076        }
3077        else if ( cache_state == CACHE_SLOT_STATE_ZOMBI ) // pending cleanup
3078        {
3079            // stalled until cleanup is acknowledged
3080            r_dcache_fsm   = DCACHE_TLB_PTE1_GET;
3081        }
3082        else            // we must load the missing cache line in dcache
3083        {
3084            r_dcache_vci_miss_req  = true;
3085            r_dcache_vci_paddr     = r_dcache_tlb_paddr.read();
3086            r_dcache_save_paddr    = r_dcache_tlb_paddr.read();
3087            r_dcache_miss_type     = PTE1_MISS;
3088            r_dcache_fsm           = DCACHE_MISS_SELECT;
3089
3090#if DEBUG_DCACHE
3091if ( m_debug_activated )
3092{
3093    std::cout << "  <PROC " << name() 
3094              << " DCACHE_TLB_PTE1_GET> MISS in dcache:"
3095              << " PTE1 address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
3096}
3097#endif
3098        }
3099        break;
3100    }
3101    ////////////////////////////
3102    case DCACHE_TLB_PTE1_SELECT:        // select a slot for PTE1
3103    {
3104        size_t  way;
3105        size_t  set;
3106
3107        if ( r_dcache_tlb_ins.read() )
3108        {
3109            r_itlb.select( r_dcache_tlb_vaddr.read(),
3110                           true,  // PTE1
3111                           &way,
3112                           &set );
3113#ifdef INSTRUMENTATION
3114m_cpt_itlb_read++;
3115#endif
3116        }
3117        else
3118        {
3119            r_dtlb.select( r_dcache_tlb_vaddr.read(),
3120                           true,  // PTE1
3121                           &way,
3122                           &set );
3123#ifdef INSTRUMENTATION
3124m_cpt_dtlb_read++;
3125#endif
3126        }
3127        r_dcache_tlb_way = way;
3128        r_dcache_tlb_set = set;
3129        r_dcache_fsm     = DCACHE_TLB_PTE1_UPDT;
3130
3131#if DEBUG_DCACHE
3132if ( m_debug_activated )
3133{
3134    if ( r_dcache_tlb_ins.read() )
3135        std::cout << "  <PROC " << name() 
3136                  << " DCACHE_TLB_PTE1_SELECT> Select a slot in ITLB:";
3137    else
3138        std::cout << "  <PROC " << name() 
3139                  << ".DCACHE_TLB_PTE1_SELECT> Select a slot in DTLB:";
3140        std::cout << " way = " << std::dec << way
3141                  << " / set = " << set << std::endl;
3142}
3143#endif
3144        break;
3145    }
3146    //////////////////////////
3147    case DCACHE_TLB_PTE1_UPDT:  // write a new PTE1 in tlb after testing the L/R bit
3148                                // - if L/R bit already set, exit the sub-fsm.
3149                                // - if not, we update the page table but we dont write
3150                                //   neither in DCACHE, nor in TLB, as this will be done by
3151                                //   the coherence mechanism.
3152    {
3153        paddr_t   nline    = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);
3154        uint32_t  pte      = r_dcache_tlb_pte_flags.read();
3155        bool      pt_updt  = false;
3156        bool      local    = true;
3157
3158        // We should compute the access locality:
3159        // The PPN MSB bits define the destination cluster index.
3160        // The m_srcid MSB bits define the source cluster index.
3161        // The number of bits to compare depends on the number of clusters,
3162        // and can be obtained in the mapping table.
3163        // As long as this computation is not done, all access are local.
3164
3165        if ( local )                                            // local access
3166        {
3167            if ( not ((pte & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
3168            {
3169                pt_updt                = true;
3170                r_dcache_vci_cas_old    = pte;
3171                r_dcache_vci_cas_new    = pte | PTE_L_MASK;
3172                pte                    = pte | PTE_L_MASK;
3173                r_dcache_tlb_pte_flags = pte;
3174            }
3175        }
3176        else                                                    // remote access
3177        {
3178            if ( not ((pte & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
3179            {
3180                pt_updt                = true;
3181                r_dcache_vci_cas_old    = pte;
3182                r_dcache_vci_cas_new    = pte | PTE_R_MASK;
3183                pte                    = pte | PTE_R_MASK;
3184                r_dcache_tlb_pte_flags = pte;
3185            }
3186        }
3187
3188        if ( not pt_updt )                                      // update TLB and return
3189        {
3190            if ( r_dcache_tlb_ins.read() )
3191            {
3192                r_itlb.write( true,             // 2M page
3193                              pte,
3194                              0,                // argument unused for a PTE1
3195                              r_dcache_tlb_vaddr.read(),
3196                              r_dcache_tlb_way.read(),
3197                              r_dcache_tlb_set.read(),
3198                              nline );
3199#ifdef INSTRUMENTATION
3200m_cpt_itlb_write++;
3201#endif
3202
3203#if DEBUG_DCACHE
3204if ( m_debug_activated )
3205{
3206    std::cout << "  <PROC " << name() 
3207              << " DCACHE_TLB_PTE1_UPDT> write PTE1 in ITLB"
3208              << " / set = " << std::dec << r_dcache_tlb_set.read()
3209              << " / way = " << r_dcache_tlb_way.read() << std::endl;
3210    r_itlb.printTrace();
3211}
3212#endif
3213            }
3214            else
3215            {
3216                r_dtlb.write( true,             // 2M page
3217                              pte,
3218                              0,                // argument unused for a PTE1
3219                              r_dcache_tlb_vaddr.read(),
3220                              r_dcache_tlb_way.read(),
3221                              r_dcache_tlb_set.read(),
3222                              nline );
3223#ifdef INSTRUMENTATION
3224m_cpt_dtlb_write++;
3225#endif
3226
3227#if DEBUG_DCACHE
3228if ( m_debug_activated )
3229{
3230    std::cout << "  <PROC " << name() 
3231              << " DCACHE_TLB_PTE1_UPDT> write PTE1 in DTLB"
3232              << " / set = " << std::dec << r_dcache_tlb_set.read()
3233              << " / way = " << r_dcache_tlb_way.read() << std::endl;
3234    r_dtlb.printTrace();
3235}
3236#endif
3237            }
3238            r_dcache_fsm = DCACHE_TLB_RETURN;
3239        }
3240        else                            // update page table but not TLB
3241        {
3242            r_dcache_fsm = DCACHE_TLB_LR_UPDT;
3243
3244#if DEBUG_DCACHE
3245if ( m_debug_activated )
3246{
3247    std::cout << "  <PROC " << name() 
3248              << " DCACHE_TLB_PTE1_UPDT> L/R bit update required"
3249              << std::endl;
3250}
3251#endif
3252        }
3253        break;
3254    }
3255    /////////////////////////
3256    case DCACHE_TLB_PTE2_GET:   // Try to get a PTE2 (64 bits) in the dcache
3257    {
3258        // coherence clack request (from DSPIN CLACK)
3259        if ( r_dcache_clack_req.read() )
3260        {
3261            r_dcache_fsm = DCACHE_CC_CHECK;
3262            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3263            break;
3264        }
3265
3266        // coherence request (from CC_RECEIVE FSM)
3267        if ( r_cc_receive_dcache_req.read() )
3268        {
3269            r_dcache_fsm = DCACHE_CC_CHECK;
3270            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3271            break;
3272        }
3273
3274        uint32_t        pte_flags;
3275        uint32_t        pte_ppn;
3276        size_t          way;
3277        size_t          set;
3278        size_t          word;
3279        int         cache_state;
3280
3281        r_dcache.read( r_dcache_tlb_paddr.read(),
3282                       &pte_flags,
3283                       &pte_ppn,
3284                       &way,
3285                       &set,
3286                       &word,
3287                       &cache_state );
3288#ifdef INSTRUMENTATION
3289m_cpt_dcache_data_read++;
3290m_cpt_dcache_dir_read++;
3291#endif
3292        if ( cache_state == CACHE_SLOT_STATE_VALID )   // hit in dcache
3293        {
3294            if ( not (pte_flags & PTE_V_MASK) ) // unmapped
3295            {
3296                if ( r_dcache_tlb_ins.read() )
3297                {
3298                    r_mmu_ietr             = MMU_READ_PT2_UNMAPPED;
3299                    r_mmu_ibvar            = r_dcache_tlb_vaddr.read();
3300                    r_icache_tlb_miss_req  = false;
3301                    r_icache_tlb_rsp_error = true;
3302                }
3303                else
3304                {
3305                    r_mmu_detr             = MMU_READ_PT2_UNMAPPED;
3306                    r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
3307                    m_drsp.valid           = true;
3308                    m_drsp.error           = true;
3309                }
3310                r_dcache_fsm               = DCACHE_IDLE;
3311
3312#if DEBUG_DCACHE
3313if ( m_debug_activated )
3314{
3315    std::cout << "  <PROC " << name()
3316              << " DCACHE_TLB_PTE2_GET> HIT in dcache, but PTE unmapped"
3317              << " PTE_FLAGS = " << std::hex << pte_flags
3318              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3319}
3320#endif
3321            }
3322            else                                // mapped : we must update the TLB
3323            {
3324                r_dcache_in_tlb[m_dcache_sets*way+set] = true;
3325                r_dcache_tlb_pte_flags  = pte_flags;
3326                r_dcache_tlb_pte_ppn    = pte_ppn;
3327                r_dcache_tlb_cache_way  = way;
3328                r_dcache_tlb_cache_set  = set;
3329                r_dcache_tlb_cache_word = word;
3330                r_dcache_fsm            = DCACHE_TLB_PTE2_SELECT;
3331
3332#if DEBUG_DCACHE
3333if ( m_debug_activated )
3334{
3335    std::cout << "  <PROC " << name() 
3336              << " DCACHE_TLB_PTE2_GET> HIT in dcache:"
3337              << " PTE_FLAGS = " << std::hex << pte_flags
3338              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3339}
3340#endif
3341             }
3342        }
3343        else if ( cache_state == CACHE_SLOT_STATE_ZOMBI ) // pending cleanup
3344        {
3345            // stalled until cleanup is acknowledged
3346            r_dcache_fsm   = DCACHE_TLB_PTE2_GET;
3347
3348#if DEBUG_DCACHE
3349if ( m_debug_activated )
3350{
3351    std::cout << "  <PROC " << name() 
3352              << " DCACHE_TLB_PTE2_GET> ZOMBI in dcache: waiting cleanup ack"
3353              << std::endl;
3354}
3355#endif
3356        }
3357        else            // we must load the missing cache line in dcache
3358        {
3359            r_dcache_fsm          = DCACHE_MISS_SELECT;
3360            r_dcache_vci_miss_req = true;
3361            r_dcache_vci_paddr    = r_dcache_tlb_paddr.read();
3362            r_dcache_save_paddr   = r_dcache_tlb_paddr.read();
3363            r_dcache_miss_type    = PTE2_MISS;
3364
3365#if DEBUG_DCACHE
3366if ( m_debug_activated )
3367{
3368    std::cout << "  <PROC " << name()
3369              << " DCACHE_TLB_PTE2_GET> MISS in dcache:"
3370              << " PTE address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
3371}
3372#endif
3373        }
3374        break;
3375    }
3376    ////////////////////////////
3377    case DCACHE_TLB_PTE2_SELECT:    // select a slot for PTE2
3378    {
3379        size_t way;
3380        size_t set;
3381
3382        if ( r_dcache_tlb_ins.read() )
3383        {
3384            r_itlb.select( r_dcache_tlb_vaddr.read(),
3385                           false,       // PTE2
3386                           &way,
3387                           &set );
3388#ifdef INSTRUMENTATION
3389m_cpt_itlb_read++;
3390#endif
3391        }
3392        else
3393        {
3394            r_dtlb.select( r_dcache_tlb_vaddr.read(),
3395                           false,       // PTE2
3396                           &way,
3397                           &set );
3398#ifdef INSTRUMENTATION
3399m_cpt_dtlb_read++;
3400#endif
3401        }
3402
3403#if DEBUG_DCACHE
3404if ( m_debug_activated )
3405{
3406    if ( r_dcache_tlb_ins.read() )
3407        std::cout << "  <PROC " << name()
3408                  << " DCACHE_TLB_PTE2_SELECT> Select a slot in ITLB:";
3409    else
3410        std::cout << "  <PROC " << name()
3411                  << " DCACHE_TLB_PTE2_SELECT> Select a slot in DTLB:";
3412        std::cout << " way = " << std::dec << way
3413                  << " / set = " << set << std::endl;
3414}
3415#endif
3416        r_dcache_tlb_way = way;
3417        r_dcache_tlb_set = set;
3418        r_dcache_fsm     = DCACHE_TLB_PTE2_UPDT;
3419        break;
3420    }
3421    //////////////////////////
3422    case DCACHE_TLB_PTE2_UPDT:  // write a new PTE2 in tlb after testing the L/R bit
3423                                // - if L/R bit already set, exit the sub-fsm.
3424                                // - if not, we update the page table but we dont write
3425                                //   neither in DCACHE, nor in TLB, as this will be done by
3426                                //   the coherence mechanism.
3427    {
3428        paddr_t         nline     = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);
3429        uint32_t        pte_flags = r_dcache_tlb_pte_flags.read();
3430        uint32_t        pte_ppn   = r_dcache_tlb_pte_ppn.read();
3431        bool            pt_updt   = false;
3432        bool            local     = true;
3433
3434        // We should compute the access locality:
3435        // The PPN MSB bits define the destination cluster index.
3436        // The m_srcid MSB bits define the source cluster index.
3437        // The number of bits to compare depends on the number of clusters,
3438        // and can be obtained in the mapping table.
3439        // As long as this computation is not done, all access are local.
3440
3441        if ( local )                                            // local access
3442        {
3443            if ( not ((pte_flags & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
3444            {
3445                pt_updt                = true;
3446                r_dcache_vci_cas_old   = pte_flags;
3447                r_dcache_vci_cas_new   = pte_flags | PTE_L_MASK;
3448                pte_flags              = pte_flags | PTE_L_MASK;
3449                        r_dcache_tlb_pte_flags = pte_flags;
3450            }
3451        }
3452        else                                                    // remote access
3453        {
3454            if ( not ((pte_flags & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
3455            {
3456                pt_updt                = true;
3457                r_dcache_vci_cas_old   = pte_flags;
3458                r_dcache_vci_cas_new   = pte_flags | PTE_R_MASK;
3459                pte_flags              = pte_flags | PTE_R_MASK;
3460                        r_dcache_tlb_pte_flags = pte_flags;
3461            }
3462        }
3463
3464        if ( not pt_updt )                       // update TLB
3465        {
3466            if ( r_dcache_tlb_ins.read() )
3467            {
3468                r_itlb.write( false,    // 4K page
3469                              pte_flags,
3470                              pte_ppn,
3471                              r_dcache_tlb_vaddr.read(),
3472                              r_dcache_tlb_way.read(),
3473                              r_dcache_tlb_set.read(),
3474                              nline );
3475#ifdef INSTRUMENTATION
3476m_cpt_itlb_write++;
3477#endif
3478
3479#if DEBUG_DCACHE
3480if ( m_debug_activated )
3481{
3482    std::cout << "  <PROC " << name()
3483              << " DCACHE_TLB_PTE2_UPDT> write PTE2 in ITLB"
3484              << " / set = " << std::dec << r_dcache_tlb_set.read()
3485              << " / way = " << r_dcache_tlb_way.read() << std::endl;
3486    r_itlb.printTrace();
3487}
3488#endif
3489            }
3490            else
3491            {
3492                r_dtlb.write( false,    // 4K page
3493                              pte_flags,
3494                              pte_ppn,
3495                              r_dcache_tlb_vaddr.read(),
3496                              r_dcache_tlb_way.read(),
3497                              r_dcache_tlb_set.read(),
3498                              nline );
3499#ifdef INSTRUMENTATION
3500m_cpt_dtlb_write++;
3501#endif
3502
3503#if DEBUG_DCACHE
3504if ( m_debug_activated )
3505{
3506    std::cout << "  <PROC " << name()
3507              << " DCACHE_TLB_PTE2_UPDT> write PTE2 in DTLB"
3508              << " / set = " << std::dec << r_dcache_tlb_set.read()
3509              << " / way = " << r_dcache_tlb_way.read() << std::endl;
3510    r_dtlb.printTrace();
3511}
3512#endif
3513
3514            }
3515            r_dcache_fsm = DCACHE_TLB_RETURN;
3516        }
3517        else                                   // update page table but not TLB
3518        {
3519            r_dcache_fsm = DCACHE_TLB_LR_UPDT;  // dcache and page table update
3520
3521#if DEBUG_DCACHE
3522if ( m_debug_activated )
3523{
3524    std::cout << "  <PROC " << name()
3525              << " DCACHE_TLB_PTE2_UPDT> L/R bit update required" << std::endl;
3526}
3527#endif
3528        }
3529        break;
3530    }
3531    ////////////////////////
3532    case DCACHE_TLB_LR_UPDT:        // request a CAS transaction to update L/R bit
3533    {
3534#if DEBUG_DCACHE
3535if ( m_debug_activated )
3536{
3537    std::cout << "  <PROC " << name()
3538              << " DCACHE_TLB_LR_UPDT> Update dcache: (L/R) bit" << std::endl;
3539}
3540#endif
3541        // r_dcache_vci_cas_old & r_dcache_vci_cas_new registers are already set
3542        r_dcache_vci_paddr = r_dcache_tlb_paddr.read();
3543
3544        // checking llsc reservation buffer
3545        if ( r_dcache_llsc_paddr.read() == r_dcache_tlb_paddr.read() )
3546            r_dcache_llsc_valid = false;
3547
3548        // request a CAS CMD and go to DCACHE_TLB_LR_WAIT state
3549        r_dcache_vci_cas_req = true;
3550        r_dcache_fsm         = DCACHE_TLB_LR_WAIT;
3551        break;
3552    }
3553    ////////////////////////
3554    case DCACHE_TLB_LR_WAIT:            // Waiting the response to SC transaction for DIRTY bit.
3555                                    // We consume the response in rsp FIFO,
3556                                    // and exit the sub-fsm, but we don't
3557                                    // analyse the response, because we don't
3558                                    // care if the L/R bit update is not done.
3559                                    // We must take the coherence requests because
3560                                    // there is a risk of dead-lock
3561
3562    {
3563        // coherence clack request (from DSPIN CLACK)
3564        if ( r_dcache_clack_req.read() )
3565        {
3566            r_dcache_fsm = DCACHE_CC_CHECK;
3567            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3568            break;
3569        }
3570
3571        // coherence request (from CC_RECEIVE FSM)
3572        if ( r_cc_receive_dcache_req.read() )
3573        {
3574            r_dcache_fsm = DCACHE_CC_CHECK;
3575            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3576            break;
3577        }
3578
3579        if ( r_vci_rsp_data_error.read() )      // bus error
3580        {
3581            std::cout << "BUS ERROR in DCACHE_TLB_LR_WAIT state" << std::endl;
3582            std::cout << "This should not happen in this state" << std::endl;
3583            exit(0);
3584        }
3585        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
3586        {
3587#if DEBUG_DCACHE
3588if ( m_debug_activated )
3589{
3590    std::cout << "  <PROC " << name()
3591              << " DCACHE_TLB_LR_WAIT> SC response received" << std::endl;
3592}
3593#endif
3594            vci_rsp_fifo_dcache_get = true;
3595            r_dcache_fsm            = DCACHE_TLB_RETURN;
3596        }
3597        break;
3598    }
3599    ///////////////////////
3600    case DCACHE_TLB_RETURN:             // return to caller depending on tlb miss type
3601    {
3602#if DEBUG_DCACHE
3603if ( m_debug_activated )
3604{
3605    std::cout << "  <PROC " << name()
3606              << " DCACHE_TLB_RETURN> TLB MISS completed" << std::endl;
3607}
3608#endif
3609        if ( r_dcache_tlb_ins.read() ) r_icache_tlb_miss_req = false;
3610        r_dcache_fsm = DCACHE_IDLE;
3611        break;
3612    }
3613    ///////////////////////
3614    case DCACHE_XTN_SWITCH:             // The r_ptpr registers must be written,
3615                                // and both itlb and dtlb must be flushed.
3616                                // Caution : the itlb miss requests must be taken
3617                                // to avoid dead-lock in case of simultaneous ITLB miss
3618    {
3619        // itlb miss request
3620        if ( r_icache_tlb_miss_req.read() )
3621        {
3622            r_dcache_tlb_ins    = true;
3623            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
3624            r_dcache_fsm        = DCACHE_TLB_MISS;
3625            break;
3626        }
3627
3628        if ( not r_dcache_xtn_req.read() )
3629        {
3630            r_dtlb.flush();
3631            r_mmu_ptpr   = m_dreq.wdata;
3632            r_dcache_fsm = DCACHE_IDLE;
3633            m_drsp.valid = true;
3634        }
3635        break;
3636    }
3637    /////////////////////
3638    case DCACHE_XTN_SYNC:               // waiting until write buffer empty
3639                                // The coherence request must be taken
3640                                // as there is a risk of dead-lock
3641    {
3642        // coherence clack request (from DSPIN CLACK)
3643        if ( r_dcache_clack_req.read() )
3644        {
3645            r_dcache_fsm = DCACHE_CC_CHECK;
3646            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3647            break;
3648        }
3649
3650        // coherence request (from CC_RECEIVE FSM)
3651        if ( r_cc_receive_dcache_req.read() )
3652        {
3653            r_dcache_fsm = DCACHE_CC_CHECK;
3654            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3655            break;
3656        }
3657
3658        if ( r_wbuf.empty() )
3659        {
3660            m_drsp.valid   = true;
3661            r_dcache_fsm = DCACHE_IDLE;
3662        }
3663        break;
3664    }
3665    ////////////////////////
3666    case DCACHE_XTN_IC_FLUSH:           // Waiting completion of an XTN request to the ICACHE FSM
3667    case DCACHE_XTN_IC_INVAL_VA:        // Caution : the itlb miss requests must be taken
3668    case DCACHE_XTN_IC_INVAL_PA:        // because the XTN_ICACHE_INVAL request to icache
3669    case DCACHE_XTN_IT_INVAL:           // can generate an itlb miss,
3670                                    // and because it can exist a simultaneous ITLB miss
3671    {
3672        // coherence clack request (from DSPIN CLACK)
3673        if ( r_dcache_clack_req.read() )
3674        {
3675            r_dcache_fsm = DCACHE_CC_CHECK;
3676            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3677            break;
3678        }
3679
3680        // coherence request (from CC_RECEIVE FSM)
3681        if ( r_cc_receive_dcache_req.read() )
3682        {
3683            r_dcache_fsm = DCACHE_CC_CHECK;
3684            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3685            break;
3686        }
3687
3688        // itlb miss request
3689        if ( r_icache_tlb_miss_req.read() )
3690        {
3691            r_dcache_tlb_ins    = true;
3692            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
3693            r_dcache_fsm        = DCACHE_TLB_MISS;
3694            break;
3695        }
3696
3697        // test if XTN request to icache completed
3698        if ( not r_dcache_xtn_req.read() )
3699        {
3700            r_dcache_fsm = DCACHE_IDLE;
3701            m_drsp.valid = true;
3702        }
3703        break;
3704    }
3705    /////////////////////////
3706    case DCACHE_XTN_DC_FLUSH:   // Invalidate sequencially all cache lines, using
3707                                // r_dcache_flush_count as a slot counter,
3708                                // looping in this state until all slots have been visited.
3709                                // It can require two cycles per slot:
3710                                // We test here the slot state, and make the actual inval
3711                                // (if line is valid) in DCACHE_XTN_DC_FLUSH_GO state.
3712                                // A cleanup request is generated for each valid line.
3713                                // returns to IDLE and flush TLBs when last slot
3714    {
3715        // coherence clack request (from DSPIN CLACK)
3716        if ( r_dcache_clack_req.read() )
3717        {
3718            r_dcache_fsm = DCACHE_CC_CHECK;
3719            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3720            break;
3721        }
3722
3723        // coherence request (from CC_RECEIVE FSM)
3724        if ( r_cc_receive_dcache_req.read() )
3725        {
3726            r_dcache_fsm = DCACHE_CC_CHECK;
3727            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3728            break;
3729        }
3730
3731        if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
3732        {
3733            int       state;
3734            paddr_t   tag;
3735            size_t    way = r_dcache_flush_count.read()/m_dcache_sets;
3736            size_t    set = r_dcache_flush_count.read()%m_dcache_sets;
3737
3738#ifdef INSTRUMENTATION
3739m_cpt_dcache_dir_read++;
3740#endif
3741            r_dcache.read_dir( way,
3742                               set,
3743                               &tag,
3744                               &state );
3745
3746            if ( state == CACHE_SLOT_STATE_VALID )         // inval required
3747            {
3748                // request cleanup
3749                r_dcache_cc_send_req   = true;
3750                r_dcache_cc_send_nline = tag * m_dcache_sets + set;
3751                r_dcache_cc_send_way   = way;
3752                r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
3753
3754                // goes to DCACHE_XTN_DC_FLUSH_GO to inval directory
3755                r_dcache_miss_way     = way;
3756                r_dcache_miss_set     = set;
3757                r_dcache_fsm          = DCACHE_XTN_DC_FLUSH_GO;
3758            }
3759            else if ( r_dcache_flush_count.read() ==
3760                      (m_dcache_sets*m_dcache_ways - 1) )  // last slot
3761            {
3762                r_dtlb.reset();
3763                r_itlb.reset();
3764                r_dcache_fsm = DCACHE_IDLE;
3765                m_drsp.valid = true;
3766            }
3767
3768            // saturation counter
3769            if ( r_dcache_flush_count.read() < (m_dcache_sets*m_dcache_ways - 1) )
3770                r_dcache_flush_count = r_dcache_flush_count.read() + 1;
3771        }
3772        break;
3773    }
3774    ////////////////////////////
3775    case DCACHE_XTN_DC_FLUSH_GO:    // Switch the cache slot to ZOMBI state
3776                                    // and reset directory extension.
3777                                    // returns to IDLE and flush TLBs when last slot
3778    {
3779        size_t way = r_dcache_miss_way.read();
3780        size_t set = r_dcache_miss_set.read();
3781
3782        r_dcache_in_tlb[m_dcache_sets*way+set]       = false;
3783        r_dcache_contains_ptd[m_dcache_sets*way+set] = false;
3784
3785#ifdef INSTRUMENTATION
3786m_cpt_dcache_dir_write++;
3787#endif
3788        r_dcache.write_dir( way,
3789                            set,
3790                            CACHE_SLOT_STATE_ZOMBI );
3791
3792        if ( r_dcache_flush_count.read() ==
3793             (m_dcache_sets*m_dcache_ways - 1) )  // last slot
3794        {
3795            r_dtlb.reset();
3796            r_itlb.reset();
3797            r_dcache_fsm = DCACHE_IDLE;
3798            m_drsp.valid = true;
3799        }
3800        else
3801        {
3802            r_dcache_fsm = DCACHE_XTN_DC_FLUSH;
3803        }
3804        break;
3805    }
3806    /////////////////////////
3807    case DCACHE_XTN_DT_INVAL:   // handling processor XTN_DTLB_INVAL request
3808    {
3809        r_dtlb.inval(r_dcache_save_wdata.read());
3810        r_dcache_fsm        = DCACHE_IDLE;
3811        m_drsp.valid          = true;
3812        break;
3813    }
3814    ////////////////////////////
3815    case DCACHE_XTN_DC_INVAL_VA:  // selective cache line invalidate with virtual address
3816                                  // requires 3 cycles: access tlb, read cache, inval cache
3817                                  // we compute the physical address in this state
3818    {
3819        paddr_t paddr;
3820        bool    hit;
3821
3822        if ( r_mmu_mode.read() & DATA_TLB_MASK )        // dtlb activated
3823        {
3824
3825#ifdef INSTRUMENTATION
3826m_cpt_dtlb_read++;
3827#endif
3828            hit = r_dtlb.translate( r_dcache_save_wdata.read(),
3829                                    &paddr );
3830        }
3831        else                                            // dtlb not activated
3832        {
3833            paddr = (paddr_t)r_dcache_save_wdata.read();
3834            hit   = true;
3835        }
3836
3837        if ( hit )              // tlb hit
3838        {
3839            r_dcache_save_paddr = paddr;
3840            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_PA;
3841        }
3842        else                    // tlb miss
3843        {
3844
3845#ifdef INSTRUMENTATION
3846m_cpt_dtlb_miss++;
3847#endif
3848            r_dcache_tlb_ins    = false;                // dtlb
3849            r_dcache_tlb_vaddr  = r_dcache_save_wdata.read();
3850            r_dcache_fsm        = DCACHE_TLB_MISS;
3851        }
3852
3853#if DEBUG_DCACHE
3854if ( m_debug_activated )
3855{
3856    std::cout << "  <PROC " << name()
3857              << " DCACHE_XTN_DC_INVAL_VA> Compute physical address" << std::hex
3858              << " / VADDR = " << r_dcache_save_wdata.read()
3859              << " / PADDR = " << paddr << std::endl;
3860}
3861#endif
3862
3863        break;
3864    }
3865    ////////////////////////////
3866    case DCACHE_XTN_DC_INVAL_PA:  // selective cache line invalidate with physical address
3867                                  // requires 2 cycles: read cache / inval cache
3868                                  // In this state we read dcache.
3869    {
3870        size_t          way;
3871        size_t          set;
3872        size_t          word;
3873        int         state;
3874
3875#ifdef INSTRUMENTATION
3876m_cpt_dcache_dir_read++;
3877#endif
3878        r_dcache.read_dir( r_dcache_save_paddr.read(),
3879                           &state,
3880                           &way,
3881                           &set,
3882                           &word );
3883
3884        if ( state == CACHE_SLOT_STATE_VALID )  // inval to be done
3885        {
3886            r_dcache_xtn_way = way;
3887            r_dcache_xtn_set = set;
3888            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_GO;
3889        }
3890        else            // miss : nothing to do
3891        {
3892            r_dcache_fsm      = DCACHE_IDLE;
3893            m_drsp.valid      = true;
3894        }
3895
3896#if DEBUG_DCACHE
3897if ( m_debug_activated )
3898{
3899    std::cout << "  <PROC " << name()
3900              << " DCACHE_XTN_DC_INVAL_PA> Test hit in dcache" << std::hex
3901              << " / PADDR = " << r_dcache_save_paddr.read() << std::dec
3902              << " / HIT = " << (state == CACHE_SLOT_STATE_VALID)
3903              << " / SET = " << set
3904              << " / WAY = " << way << std::endl;
3905}
3906#endif
3907        break;
3908    }
3909    ////////////////////////////
3910    case DCACHE_XTN_DC_INVAL_GO:  // In this state, we invalidate the cache line
3911                                              // Blocked if previous cleanup not completed
3912                                  // Test if itlb or dtlb inval is required
3913    {
3914        if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
3915        {
3916            size_t      way        = r_dcache_xtn_way.read();
3917            size_t      set        = r_dcache_xtn_set.read();
3918            paddr_t nline      = r_dcache_save_paddr.read() / (m_dcache_words<<2);
3919
3920#ifdef INSTRUMENTATION
3921m_cpt_dcache_dir_write++;
3922#endif
3923            r_dcache.write_dir( way,
3924                                set,
3925                                CACHE_SLOT_STATE_ZOMBI );
3926
3927            // request cleanup
3928            r_dcache_cc_send_req   = true;
3929            r_dcache_cc_send_nline = nline;
3930            r_dcache_cc_send_way   = way;
3931            r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
3932
3933            // possible itlb & dtlb invalidate
3934            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
3935            {
3936                r_dcache_tlb_inval_line = nline;
3937                r_dcache_tlb_inval_set  = 0;
3938                r_dcache_fsm_scan_save  = DCACHE_XTN_DC_INVAL_END;
3939                r_dcache_fsm            = DCACHE_INVAL_TLB_SCAN;
3940                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3941            }
3942            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
3943            {
3944                r_itlb.reset();
3945                r_dtlb.reset();
3946                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
3947                r_dcache_fsm = DCACHE_IDLE;
3948                m_drsp.valid = true;
3949            }
3950            else
3951            {
3952                r_dcache_fsm = DCACHE_IDLE;
3953                m_drsp.valid = true;
3954            }
3955
3956#if DEBUG_DCACHE
3957if ( m_debug_activated )
3958{
3959    std::cout << "  <PROC " << name()
3960              << " DCACHE_XTN_DC_INVAL_GO> Actual dcache inval" << std::hex
3961              << " / PADDR = " << r_dcache_save_paddr.read() << std::endl;
3962}
3963#endif
3964            }
3965        break;
3966    }
3967    //////////////////////////////
3968    case DCACHE_XTN_DC_INVAL_END:       // send response to processor XTN request
3969    {
3970        r_dcache_fsm = DCACHE_IDLE;
3971        m_drsp.valid = true;
3972        break;
3973    }
3974    ////////////////////////
3975    case DCACHE_MISS_SELECT:   // Try to select a slot in associative set
3976                               // if previous cleanup has been sent.
3977                               // Waiting in this state if no slot available
3978                               // Set the r_dcache_cleanup_req flip-flop
3979                               // and the r_dcache_miss_clack flip-flop
3980                               // when a cleanup is required
3981    {
3982        if ( m_dreq.valid) m_cost_data_miss_frz++;
3983
3984        // coherence clack request (from DSPIN CLACK)
3985        if ( r_dcache_clack_req.read() )
3986        {
3987            r_dcache_fsm = DCACHE_CC_CHECK;
3988            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3989            break;
3990        }
3991
3992        // coherence request (from CC_RECEIVE FSM)
3993        if ( r_cc_receive_dcache_req.read() )
3994        {
3995            r_dcache_fsm = DCACHE_CC_CHECK;
3996            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3997            break;
3998        }
3999
4000        if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
4001        {
4002            bool     found = false;
4003            bool     cleanup = false;
4004            size_t   way = 0;
4005            size_t   set = 0;
4006            paddr_t  victim = 0;
4007
4008#ifdef INSTRUMENTATION
4009m_cpt_dcache_dir_read++;
4010#endif
4011            r_dcache.read_select( r_dcache_save_paddr.read(),
4012                                  &victim,
4013                                  &way,
4014                                  &set,
4015                                  &found,
4016                                  &cleanup );
4017
4018            if ( found )
4019            {
4020                r_dcache_miss_way = way;
4021                r_dcache_miss_set = set;
4022
4023                if ( cleanup )
4024                {
4025                    r_dcache_miss_clack   = true;
4026                    r_dcache_fsm          = DCACHE_MISS_CLEAN;
4027                    // request cleanup
4028                    r_dcache_cc_send_req   = true;
4029                    r_dcache_cc_send_nline = victim;
4030                    r_dcache_cc_send_way   = way;
4031                    r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
4032                }
4033                else
4034                {
4035                    r_dcache_fsm          = DCACHE_MISS_WAIT;
4036                }
4037
4038#if DEBUG_DCACHE
4039if ( m_debug_activated )
4040{
4041    std::cout << "  <PROC " << name()
4042              << " DCACHE_MISS_SELECT> Select a slot:" << std::dec
4043              << " / WAY = "   << way
4044              << " / SET = "   << set
4045              << " / PADDR = " << std::hex << r_dcache_save_paddr.read();
4046    if(cleanup) std::cout << " / VICTIM = " << (victim*m_dcache_words*4) << std::endl;
4047    else        std::cout << std::endl;
4048}
4049#endif
4050            } // end found
4051        }
4052        break;
4053    }
4054    ///////////////////////
4055    case DCACHE_MISS_CLEAN:             // switch the slot to ZOMBI state
4056                                // and possibly request itlb or dtlb invalidate
4057    {
4058        if ( m_dreq.valid) m_cost_data_miss_frz++;
4059
4060        size_t  way   = r_dcache_miss_way.read();
4061        size_t  set   = r_dcache_miss_set.read();
4062
4063#ifdef INSTRUMENTATION
4064m_cpt_dcache_dir_read++;
4065#endif
4066        r_dcache.write_dir( way,
4067                            set,
4068                            CACHE_SLOT_STATE_ZOMBI );
4069#if DEBUG_DCACHE
4070if ( m_debug_activated )
4071{
4072    std::cout << "  <PROC " << name()
4073              << " DCACHE_MISS_CLEAN> Switch to ZOMBI state" << std::dec
4074              << " / way = "   << way
4075              << " / set = "   << set << std::endl;
4076}
4077#endif
4078        // if selective itlb & dtlb invalidate are required
4079        // the miss response is not handled before invalidate completed
4080        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
4081        {
4082            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4083            r_dcache_tlb_inval_line  = r_dcache_cc_send_nline;
4084            r_dcache_tlb_inval_set   = 0;
4085            r_dcache_fsm_scan_save   = DCACHE_MISS_WAIT;
4086            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4087        }
4088        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
4089        {
4090            r_itlb.reset();
4091            r_dtlb.reset();
4092            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4093            r_dcache_fsm = DCACHE_MISS_WAIT;
4094        }
4095        else
4096        {
4097            r_dcache_fsm = DCACHE_MISS_WAIT;
4098        }
4099        break;
4100    }
4101    //////////////////////
4102    case DCACHE_MISS_WAIT:      // waiting the response to a miss request from VCI_RSP FSM
4103                            // This state is in charge of error signaling
4104                            // There is 5 types of error depending on the requester
4105    {
4106        if ( m_dreq.valid) m_cost_data_miss_frz++;
4107
4108        // coherence clack request (from DSPIN CLACK)
4109        if ( r_dcache_clack_req.read() )
4110        {
4111            r_dcache_fsm = DCACHE_CC_CHECK;
4112            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4113            break;
4114        }
4115
4116        // coherence request (from CC_RECEIVE FSM)
4117        if ( r_cc_receive_dcache_req.read() )
4118        {
4119            r_dcache_fsm = DCACHE_CC_CHECK;
4120            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4121            break;
4122        }
4123
4124        if ( r_vci_rsp_data_error.read() )                      // bus error
4125        {
4126            switch ( r_dcache_miss_type.read() )
4127            {
4128                case PROC_MISS:
4129                {
4130                    r_mmu_detr            = MMU_READ_DATA_ILLEGAL_ACCESS;
4131                    r_mmu_dbvar           = r_dcache_save_vaddr.read();
4132                    m_drsp.valid            = true;
4133                    m_drsp.error            = true;
4134                    r_dcache_fsm          = DCACHE_IDLE;
4135                    break;
4136                }
4137                case PTE1_MISS:
4138                {
4139                    if ( r_dcache_tlb_ins.read() )
4140                    {
4141                        r_mmu_ietr              = MMU_READ_PT1_ILLEGAL_ACCESS;
4142                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
4143                        r_icache_tlb_miss_req   = false;
4144                        r_icache_tlb_rsp_error  = true;
4145                    }
4146                    else
4147                    {
4148                        r_mmu_detr              = MMU_READ_PT1_ILLEGAL_ACCESS;
4149                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
4150                        m_drsp.valid              = true;
4151                        m_drsp.error              = true;
4152                    }
4153                    r_dcache_fsm                = DCACHE_IDLE;
4154                    break;
4155                }
4156                case PTE2_MISS:
4157                {
4158                    if ( r_dcache_tlb_ins.read() )
4159                    {
4160                        r_mmu_ietr              = MMU_READ_PT2_ILLEGAL_ACCESS;
4161                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
4162                        r_icache_tlb_miss_req   = false;
4163                        r_icache_tlb_rsp_error  = true;
4164                    }
4165                    else
4166                    {
4167                        r_mmu_detr              = MMU_READ_PT2_ILLEGAL_ACCESS;
4168                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
4169                        m_drsp.valid              = true;
4170                        m_drsp.error              = true;
4171                    }
4172                    r_dcache_fsm                = DCACHE_IDLE;
4173                    break;
4174                }
4175            } // end switch type
4176            r_vci_rsp_data_error = false;
4177        }
4178        else if ( r_vci_rsp_fifo_dcache.rok() )         // valid response available
4179        {
4180            r_dcache_miss_word = 0;
4181                r_dcache_fsm       = DCACHE_MISS_DATA_UPDT;
4182        }
4183        break;
4184    }
4185    //////////////////////////
4186    case DCACHE_MISS_DATA_UPDT:   // update the dcache (one word per cycle)
4187    {
4188        if ( m_dreq.valid) m_cost_data_miss_frz++;
4189
4190        if ( r_vci_rsp_fifo_dcache.rok() )      // one word available
4191        {
4192#ifdef INSTRUMENTATION
4193m_cpt_dcache_data_write++;
4194#endif
4195                r_dcache.write( r_dcache_miss_way.read(),
4196                                r_dcache_miss_set.read(),
4197                                r_dcache_miss_word.read(),
4198                                r_vci_rsp_fifo_dcache.read() );
4199#if DEBUG_DCACHE
4200if ( m_debug_activated )
4201{
4202    std::cout << "  <PROC " << name()
4203              << " DCACHE_MISS_DATA_UPDT> Write one word:"
4204              << " / DATA = "  << std::hex << r_vci_rsp_fifo_dcache.read()
4205              << " / WAY = "   << std::dec << r_dcache_miss_way.read()
4206              << " / SET = "   << r_dcache_miss_set.read()
4207              << " / WORD = "  << r_dcache_miss_word.read() << std::endl;
4208}
4209#endif
4210            vci_rsp_fifo_dcache_get = true;
4211            r_dcache_miss_word = r_dcache_miss_word.read() + 1;
4212
4213            if ( r_dcache_miss_word.read() == (m_dcache_words-1) ) // last word
4214            {
4215                r_dcache_fsm = DCACHE_MISS_DIR_UPDT;
4216            }
4217        }
4218        break;
4219    }
4220    //////////////////////////
4221    case DCACHE_MISS_DIR_UPDT:  // Stalled if a victim line has been evicted
4222                                // and the cleanup ack has not been received,
4223                                // as indicated by the r_dcache_miss clack.
4224                                // - If no matching coherence request (r_dcache_inval_miss)
4225                                //   switch directory slot to VALID state.
4226                                // - If matching coherence request, switch directory slot
4227                                //   to ZOMBI state, and send a cleanup request.
4228    {
4229        if ( m_dreq.valid) m_cost_data_miss_frz++;
4230
4231        // coherence clack request (from DSPIN CLACK)
4232        if ( r_dcache_clack_req.read() )
4233        {
4234            r_dcache_fsm = DCACHE_CC_CHECK;
4235            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4236            break;
4237        }
4238
4239        // coherence request (from CC_RECEIVE FSM)
4240        if ( r_cc_receive_dcache_req.read() )
4241        {
4242            r_dcache_fsm = DCACHE_CC_CHECK;
4243            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4244            break;
4245        }
4246
4247        if ( not r_dcache_miss_clack.read() )  // waiting cleanup acknowledge
4248        {
4249            if ( r_dcache_miss_inval.read() ) // switch slot to ZOMBI state, and new cleanup
4250            {
4251                if ( not r_dcache_cc_send_req.read() ) // blocked until previous request sent
4252                {
4253                    r_dcache_miss_inval     = false;
4254                    // request cleanup
4255                    r_dcache_cc_send_req   = true;
4256                    r_dcache_cc_send_nline = r_dcache_save_paddr.read()/(m_dcache_words<<2);
4257                    r_dcache_cc_send_way   = r_dcache_miss_way.read();
4258                    r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
4259
4260#ifdef INSTRUMENTATION
4261m_cpt_dcache_dir_write++;
4262#endif
4263                    r_dcache.write_dir( r_dcache_save_paddr.read(),
4264                                        r_dcache_miss_way.read(),
4265                                        r_dcache_miss_set.read(),
4266                                        CACHE_SLOT_STATE_ZOMBI );
4267#if DEBUG_DCACHE
4268if ( m_debug_activated )
4269std::cout << "  <PROC " << name()
4270          << " DCACHE_MISS_DIR_UPDT> Switch slot to ZOMBI state"
4271          << " PADDR = " << std::hex << r_dcache_save_paddr.read()
4272          << " / WAY = "   << std::dec << r_dcache_miss_way.read()
4273          << " / SET = "   << r_dcache_miss_set.read() << std::endl;
4274#endif
4275                }
4276                else
4277                    break;
4278            }
4279            else                              // switch slot to VALID state
4280            {
4281
4282#ifdef INSTRUMENTATION
4283m_cpt_dcache_dir_write++;
4284#endif
4285                r_dcache.write_dir( r_dcache_save_paddr.read(),
4286                                    r_dcache_miss_way.read(),
4287                                    r_dcache_miss_set.read(),
4288                                    CACHE_SLOT_STATE_VALID );
4289
4290#if DEBUG_DCACHE
4291if ( m_debug_activated )
4292std::cout << "  <PROC " << name()
4293          << " DCACHE_MISS_DIR_UPDT> Switch slot to VALID state"
4294          << " PADDR = " << std::hex << r_dcache_save_paddr.read()
4295          << " / WAY = "   << std::dec << r_dcache_miss_way.read()
4296          << " / SET = "   << r_dcache_miss_set.read() << std::endl;
4297#endif
4298                // reset directory extension
4299                size_t way = r_dcache_miss_way.read();
4300                size_t set = r_dcache_miss_set.read();
4301                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4302                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4303            }
4304            if      (r_dcache_miss_type.read()==PTE1_MISS) r_dcache_fsm = DCACHE_TLB_PTE1_GET;
4305            else if (r_dcache_miss_type.read()==PTE2_MISS) r_dcache_fsm = DCACHE_TLB_PTE2_GET;
4306            else                                           r_dcache_fsm = DCACHE_IDLE;
4307        }
4308        break;
4309    }
4310    /////////////////////
4311    case DCACHE_UNC_WAIT:  // waiting a response to an uncacheable read
4312    {
4313        // coherence clack request (from DSPIN CLACK)
4314        if ( r_dcache_clack_req.read() )
4315        {
4316            r_dcache_fsm = DCACHE_CC_CHECK;
4317            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4318            break;
4319        }
4320
4321        // coherence request (from CC_RECEIVE FSM)
4322        if ( r_cc_receive_dcache_req.read() )
4323        {
4324            r_dcache_fsm = DCACHE_CC_CHECK;
4325            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4326            break;
4327        }
4328
4329        if ( r_vci_rsp_data_error.read() )      // bus error
4330        {
4331            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS;
4332            r_mmu_dbvar          = m_dreq.addr;
4333            r_vci_rsp_data_error = false;
4334            m_drsp.error         = true;
4335            m_drsp.valid         = true;
4336            r_dcache_fsm         = DCACHE_IDLE;
4337            break;
4338        }
4339            else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
4340            {
4341            // consume data
4342            vci_rsp_fifo_dcache_get = true;
4343            r_dcache_fsm            = DCACHE_IDLE;
4344
4345            // acknowledge the processor request if it has not been modified
4346            if ( m_dreq.valid and (m_dreq.addr == r_dcache_save_vaddr.read()) )
4347            {
4348                    m_drsp.valid        = true;
4349                m_drsp.error        = false;
4350                    m_drsp.rdata        = r_vci_rsp_fifo_dcache.read();
4351            }
4352            }
4353        break;
4354    }
4355    /////////////////////
4356    case DCACHE_LL_WAIT:    // waiting VCI response to a LL transaction
4357    {
4358        // coherence clack request (from DSPIN CLACK)
4359        if ( r_dcache_clack_req.read() )
4360        {
4361            r_dcache_fsm = DCACHE_CC_CHECK;
4362            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4363            break;
4364        }
4365
4366        // coherence request (from CC_RECEIVE FSM)
4367        if ( r_cc_receive_dcache_req.read() )
4368        {
4369            r_dcache_fsm = DCACHE_CC_CHECK;
4370            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4371            break;
4372        }
4373
4374        if ( r_vci_rsp_data_error.read() )      // bus error
4375        {
4376            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS;
4377            r_mmu_dbvar          = m_dreq.addr;
4378            r_vci_rsp_data_error = false;
4379            m_drsp.error         = true;
4380            m_drsp.valid         = true;
4381            r_dcache_fsm         = DCACHE_IDLE;
4382            break;
4383        }
4384            else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
4385            {
4386            // consume data
4387            vci_rsp_fifo_dcache_get = true;
4388
4389            if(r_dcache_ll_rsp_count.read() == 0) // first flit
4390            {
4391                // set key value in llsc reservation buffer
4392                r_dcache_llsc_key     = r_vci_rsp_fifo_dcache.read();
4393                r_dcache_ll_rsp_count = r_dcache_ll_rsp_count.read() + 1 ;
4394            }
4395            else                                  // last flit
4396            {
4397                // acknowledge the processor request if it has not been modified
4398                if ( m_dreq.valid and (m_dreq.addr == r_dcache_save_vaddr.read()) )
4399                {
4400                    m_drsp.valid        = true;
4401                    m_drsp.error        = false;
4402                    m_drsp.rdata        = r_vci_rsp_fifo_dcache.read();
4403                }
4404                r_dcache_fsm = DCACHE_IDLE;
4405            }
4406            }
4407        break;
4408    }
4409    ////////////////////
4410    case DCACHE_SC_WAIT:        // waiting VCI response to a SC transaction
4411    {
4412        // coherence clack request (from DSPIN CLACK)
4413        if ( r_dcache_clack_req.read() )
4414        {
4415            r_dcache_fsm = DCACHE_CC_CHECK;
4416            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4417            break;
4418        }
4419
4420        // coherence request (from CC_RECEIVE FSM)
4421        if ( r_cc_receive_dcache_req.read() )
4422        {
4423            r_dcache_fsm = DCACHE_CC_CHECK;
4424            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4425            break;
4426        }
4427
4428        if ( r_vci_rsp_data_error.read() )              // bus error
4429        {
4430            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS;
4431            r_mmu_dbvar          = m_dreq.addr;
4432            r_vci_rsp_data_error = false;
4433            m_drsp.error         = true;
4434            m_drsp.valid         = true;
4435            r_dcache_fsm         = DCACHE_IDLE;
4436            break;
4437        }
4438            else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
4439            {
4440            // consume response
4441            vci_rsp_fifo_dcache_get = true;
4442            m_drsp.valid            = true;
4443            m_drsp.rdata            = r_vci_rsp_fifo_dcache.read();
4444            r_dcache_fsm            = DCACHE_IDLE;
4445            }
4446        break;
4447    }
4448    //////////////////////////
4449    case DCACHE_DIRTY_GET_PTE:          // This sub_fsm set the PTE Dirty bit in memory
4450                                    // before handling a processor WRITE or SC request
4451                                    // Input argument is r_dcache_dirty_paddr
4452                                    // In this first state, we get PTE value in dcache
4453                                    // and post a CAS request to CMD FSM
4454    {
4455        // get PTE in dcache
4456        uint32_t pte;
4457        size_t   way;
4458        size_t   set;
4459        size_t   word; // unused
4460        int      state;
4461
4462#ifdef INSTRUMENTATION
4463m_cpt_dcache_data_read++;
4464m_cpt_dcache_dir_read++;
4465#endif
4466        r_dcache.read( r_dcache_dirty_paddr.read(),
4467                       &pte,
4468                       &way,
4469                       &set,
4470                       &word,
4471                       &state );
4472
4473        assert( (state == CACHE_SLOT_STATE_VALID) and
4474        "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
4475
4476        // request CAS transaction to CMD_FSM
4477        r_dcache_dirty_way  = way;
4478        r_dcache_dirty_set  = set;
4479
4480        // check llsc reservation buffer
4481        if (r_dcache_llsc_paddr.read() == r_dcache_dirty_paddr.read() )
4482            r_dcache_llsc_valid = false;
4483
4484        // request a CAS CMD and go to DCACHE_DIRTY_WAIT state
4485        r_dcache_vci_cas_req = true;
4486        r_dcache_vci_paddr   = r_dcache_dirty_paddr.read();
4487        r_dcache_vci_cas_old = pte;
4488        r_dcache_vci_cas_new = pte | PTE_D_MASK;
4489        r_dcache_fsm         = DCACHE_DIRTY_WAIT;
4490
4491#if DEBUG_DCACHE
4492if ( m_debug_activated )
4493{
4494    std::cout << "  <PROC " << name()
4495              << " DCACHE_DIRTY_GET_PTE> CAS request" << std::hex
4496              << " / PTE_PADDR = " << r_dcache_dirty_paddr.read()
4497              << " / PTE_VALUE = " << pte << std::dec
4498              << " / SET = " << set
4499              << " / WAY = " << way << std::endl;
4500}
4501#endif
4502        break;
4503    }
4504    ///////////////////////
4505    case DCACHE_DIRTY_WAIT:         // wait completion of CAS for PTE Dirty bit,
4506                                    // and return to IDLE state when response is received.
4507                                    // we don't care if the CAS is a failure:
4508                                    // - if the CAS is a success, the coherence mechanism
4509                                    //   updates the local copy.
4510                                    // - if the CAS is a failure, we just retry the write.
4511    {
4512        // coherence clack request (from DSPIN CLACK)
4513        if ( r_dcache_clack_req.read() )
4514        {
4515            r_dcache_fsm = DCACHE_CC_CHECK;
4516            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4517            break;
4518        }
4519
4520        // coherence request (from CC_RECEIVE FSM)
4521        if ( r_cc_receive_dcache_req.read() )
4522        {
4523            r_dcache_fsm = DCACHE_CC_CHECK;
4524            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4525            break;
4526        }
4527
4528        if ( r_vci_rsp_data_error.read() )      // bus error
4529        {
4530            std::cout << "BUS ERROR in DCACHE_DIRTY_WAIT state" << std::endl;
4531            std::cout << "This should not happen in this state" << std::endl;
4532            exit(0);
4533        }
4534        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
4535        {
4536            vci_rsp_fifo_dcache_get = true;
4537            r_dcache_fsm            = DCACHE_IDLE;
4538
4539#if DEBUG_DCACHE
4540if ( m_debug_activated )
4541{
4542    std::cout << "  <PROC " << name()
4543              << " DCACHE_DIRTY_WAIT> CAS completed" << std::endl;
4544}
4545#endif
4546        }
4547        break;
4548    }
4549    /////////////////////
4550    case DCACHE_CC_CHECK:   // This state is the entry point for the sub-FSM
4551                            // handling coherence requests for DCACHE.
4552                            // If there is a matching pending miss on the modified cache
4553                            // line this is signaled in the r_dcache_miss inval flip-flop.
4554                            // If the updated (or invalidated) cache line has copies in TLBs
4555                            // these TLB copies are invalidated.
4556                            // The return state is defined in r_dcache_fsm_cc_save
4557    {
4558        paddr_t  paddr = r_cc_receive_dcache_nline.read() * m_dcache_words * 4;
4559        paddr_t  mask = ~((m_dcache_words<<2)-1);
4560
4561#if DEBUG_DCACHE
4562if ( m_debug_activated )
4563{
4564    std::cout << "  <PROC " << name()
4565              << " DCACHE_CC_CHECK> paddr = " << paddr
4566              << " r_dcache_vci_paddr = " << r_dcache_vci_paddr.read()
4567              << " mask = " << mask
4568              << " (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) = " 
4569              << (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT)
4570              << " (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT) = " 
4571              << (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT)
4572              << " ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) = " 
4573              << ((r_dcache_vci_paddr.read() & mask) == (paddr & mask))
4574              <<std::endl;
4575}
4576#endif
4577
4578       
4579        // Match between MISS address and CC address
4580        // note: In the same cycle we can handle a CLACK and a MISS match
4581        // because the CLACK access the directory but the MISS match dont.
4582        if (r_cc_receive_dcache_req.read() and
4583          ((r_dcache_fsm_cc_save == DCACHE_MISS_SELECT  )  or
4584           (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT    )  or
4585           (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT)) and
4586          ((r_dcache_vci_paddr.read() & mask) == (paddr & mask))) // matching
4587        {
4588            // signaling matching
4589            r_dcache_miss_inval = true;
4590
4591            // in case of update, go to CC_UPDT
4592            // JUST TO POP THE FIFO
4593            if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)
4594            {
4595                r_dcache_fsm        = DCACHE_CC_UPDT;
4596                r_dcache_cc_word    = r_cc_receive_word_idx.read();
4597
4598                // just pop the fifo , don't write in icache
4599                r_dcache_cc_need_write = false;
4600            }
4601            // the request is dealt with
4602            else
4603            {
4604                r_cc_receive_dcache_req = false;
4605                r_dcache_fsm            = r_dcache_fsm_cc_save.read();
4606            }
4607
4608#if DEBUG_DCACHE
4609if ( m_debug_activated )
4610{
4611    std::cout << "  <PROC " << name()
4612              << " DCACHE_CC_CHECK> Coherence request matching a pending miss:"
4613              << " PADDR = " << std::hex << paddr << std::endl;
4614}
4615#endif
4616        }
4617
4618        // CLACK handler
4619        // We switch the directory slot to EMPTY state and reset
4620        // r_dcache_miss_clack if the cleanup ack is matching a pending miss.
4621        if ( r_dcache_clack_req.read() )
4622        {
4623            if ( m_dreq.valid ) m_cost_data_miss_frz++;
4624
4625#ifdef INSTRUMENTATION
4626m_cpt_dcache_dir_write++;
4627#endif
4628            r_dcache.write_dir( 0,
4629                                r_dcache_clack_way.read(),
4630                                r_dcache_clack_set.read(),
4631                                CACHE_SLOT_STATE_EMPTY);
4632
4633            if ( (r_dcache_miss_set.read() == r_dcache_clack_set.read()) and
4634                 (r_dcache_miss_way.read() == r_dcache_clack_way.read()) )
4635            {
4636                  r_dcache_miss_clack = false;
4637            }
4638
4639            r_dcache_clack_req = false;
4640
4641            // return to cc_save state if no pending CC request
4642            if ( not r_cc_receive_dcache_req.read() )
4643            {
4644                r_dcache_fsm = r_dcache_fsm_cc_save.read() ;
4645            }
4646
4647#if DEBUG_DCACHE
4648if ( m_debug_activated )
4649{
4650    std::cout << "  <PROC " << name()
4651              << " DCACHE_CC_CHECK> CC_TYPE_CLACK Switch slot to EMPTY state"
4652              << " set = " << r_dcache_clack_set.read()
4653              << " / way = " << r_dcache_clack_way.read() << std::endl;
4654}
4655#endif
4656            break;
4657        }
4658
4659        // CC request handler
4660       
4661        int    state = 0;
4662        size_t way   = 0;
4663        size_t set   = 0;
4664        size_t word  = 0;
4665
4666#ifdef INSTRUMENTATION
4667m_cpt_dcache_dir_read++;
4668#endif
4669        r_dcache.read_dir( paddr,
4670                           &state,
4671                           &way,
4672                           &set,
4673                           &word ); // unused
4674
4675        r_dcache_cc_way = way;
4676        r_dcache_cc_set = set;
4677
4678        if ( state == CACHE_SLOT_STATE_VALID) // hit
4679        {
4680            // need to update the cache state
4681            if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT) // hit update
4682            {
4683                r_dcache_cc_need_write = true;
4684                r_dcache_fsm           = DCACHE_CC_UPDT;
4685                r_dcache_cc_word       = r_cc_receive_word_idx.read();
4686            }
4687            else if ( r_cc_receive_dcache_type.read() == CC_TYPE_INVAL ) // hit inval
4688            {
4689                r_dcache_fsm           = DCACHE_CC_INVAL;
4690            }
4691        }
4692        else                                  // miss
4693        {
4694            // multicast acknowledgement required in case of update
4695            if(r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)
4696            {
4697                r_dcache_fsm           = DCACHE_CC_UPDT;
4698                r_dcache_cc_word       = r_cc_receive_word_idx.read();
4699
4700                // just pop the fifo , don't write in icache
4701                r_dcache_cc_need_write = false;
4702            }
4703            else // No response needed
4704            {
4705                r_cc_receive_dcache_req = false;
4706                r_dcache_fsm            = r_dcache_fsm_cc_save.read();
4707            }
4708        }
4709
4710#if DEBUG_DCACHE
4711if ( m_debug_activated )
4712{
4713    std::cout << "  <PROC " << name()
4714              << " DCACHE_CC_CHECK> Coherence request received:"
4715              << " PADDR = " << std::hex << paddr
4716              << " / TYPE = " << std::dec << r_cc_receive_dcache_type.read()
4717              << " / HIT = " << (state == CACHE_SLOT_STATE_VALID) << std::endl;
4718}
4719#endif
4720
4721        break;
4722    }
4723    /////////////////////
4724    case DCACHE_CC_INVAL: // hit inval: switch slot to ZOMBI state and send a
4725                          // CLEANUP after possible invalidation of copies in
4726                          // TLBs
4727    {
4728        size_t way    = r_dcache_cc_way.read();
4729        size_t set    = r_dcache_cc_set.read();
4730
4731        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )       // selective TLB inval
4732        {
4733            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4734            r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
4735            r_dcache_tlb_inval_set   = 0;
4736            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
4737            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4738            break;
4739        }
4740
4741        if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) // TLB flush
4742        {
4743            r_itlb.reset();
4744            r_dtlb.reset();
4745            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4746
4747#if DEBUG_DCACHE
4748if ( m_debug_activated )
4749{
4750    std::cout << "  <PROC " << name()
4751              << " DCACHE_CC_INVAL> Flush DTLB & ITLB" << std::endl;
4752}
4753#endif
4754        }
4755
4756        // return to CC_CHECK if pending request to CC_SEND
4757        // to handle possible pending CLACK and avoid deadlock
4758        if ( r_dcache_cc_send_req.read() )
4759        {
4760            r_dcache_fsm = DCACHE_CC_CHECK;
4761            break;
4762        }
4763
4764        // Switch slot state to ZOMBI and send CLEANUP command
4765        r_dcache.write_dir( 0,
4766                            way,
4767                            set,
4768                            CACHE_SLOT_STATE_ZOMBI );
4769
4770        // coherence request completed
4771        r_cc_receive_dcache_req = false;
4772        r_dcache_cc_send_req    = true;
4773        r_dcache_cc_send_nline  = r_cc_receive_dcache_nline.read();
4774        r_dcache_cc_send_way    = r_dcache_cc_way.read();
4775        r_dcache_cc_send_type   = CC_TYPE_CLEANUP;
4776        r_dcache_fsm            = r_dcache_fsm_cc_save.read();
4777
4778#if DEBUG_DCACHE
4779if ( m_debug_activated )
4780{
4781    std::cout << "  <PROC " << name()
4782        << " DCACHE_CC_INVAL> Switch slot to EMPTY state:" << std::dec
4783        << " / WAY = " << way
4784        << " / SET = " << set << std::endl;
4785}
4786#endif
4787        break;
4788    }
4789    ///////////////////
4790    case DCACHE_CC_UPDT:        // hit update: write one word per cycle,
4791                                // after possible invalidation of copies in TLBs
4792    {
4793        size_t word       = r_dcache_cc_word.read();
4794        size_t way        = r_dcache_cc_way.read();
4795        size_t set        = r_dcache_cc_set.read();
4796
4797        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )       // selective TLB inval
4798        {
4799            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4800            r_dcache_tlb_inval_line = r_cc_receive_dcache_nline.read();
4801            r_dcache_tlb_inval_set  = 0;
4802            r_dcache_fsm_scan_save  = r_dcache_fsm.read();
4803            r_dcache_fsm            = DCACHE_INVAL_TLB_SCAN;
4804
4805            break;
4806        }
4807
4808        if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) // TLB flush
4809        {
4810            r_itlb.reset();
4811            r_dtlb.reset();
4812            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4813
4814#if DEBUG_DCACHE
4815if ( m_debug_activated )
4816{
4817    std::cout << "  <PROC " << name()
4818              << " DCACHE_CC_UPDT> Flush DTLB & ITLB" << std::endl;
4819}
4820#endif
4821        }
4822
4823        // if pending request to CC_SEND or if the CC_UPDT data is not ready to
4824        // handle possible pending CLACK and avoid deadlock
4825        if ( r_dcache_cc_send_req.read() )
4826        {
4827            r_dcache_fsm = DCACHE_CC_CHECK;
4828            break;
4829        }
4830       
4831        if ( not r_cc_receive_updt_fifo_be.rok() ) break;
4832
4833        if (r_dcache_cc_need_write.read())
4834        {
4835       
4836#ifdef INSTRUMENTATION
4837m_cpt_dcache_data_write++;
4838#endif
4839            r_dcache.write( way,
4840                            set,
4841                            word,
4842                            r_cc_receive_updt_fifo_data.read(),
4843                            r_cc_receive_updt_fifo_be.read() );
4844
4845            r_dcache_cc_word = word + 1;
4846
4847#if DEBUG_DCACHE
4848if ( m_debug_activated )
4849{
4850    std::cout << "  <PROC " << name()
4851              << " DCACHE_CC_UPDT> Write one word" << std::dec
4852              << " / WAY = " << way
4853              << " / SET = " << set
4854              << " / WORD = " << word
4855              << " / VALUE = " << std::hex << r_cc_receive_updt_fifo_data.read() << std::endl;
4856}
4857#endif
4858        }
4859
4860        if ( r_cc_receive_updt_fifo_eop.read() )  // last word
4861        {
4862            // no need to write in the cache anymore
4863            r_dcache_cc_need_write = false;
4864
4865            // coherence request completed
4866            r_cc_receive_dcache_req = false;
4867
4868            // request multicast acknowledgement
4869            r_dcache_cc_send_req          = true;
4870            r_dcache_cc_send_nline        = r_cc_receive_dcache_nline.read();
4871            r_dcache_cc_send_updt_tab_idx = r_cc_receive_dcache_updt_tab_idx.read();
4872            r_dcache_cc_send_type         = CC_TYPE_MULTI_ACK;
4873
4874            r_dcache_fsm                  = r_dcache_fsm_cc_save.read();
4875        }
4876
4877        //consume fifo if not eop
4878        cc_receive_updt_fifo_get  = true;
4879
4880        break;
4881    }
4882    ///////////////////////////
4883    case DCACHE_INVAL_TLB_SCAN:         // Scan sequencially all sets for both ITLB & DTLB
4884                                        // It makes assumption: m_itlb_sets == m_dtlb_sets
4885                                        // All ways are handled in parallel.
4886                                        // We enter this state when a DCACHE line is modified,
4887                                        // and there is a copy in itlb or dtlb.
4888                                        // It can be caused by:
4889                                        // - a coherence inval or updt transaction,
4890                                        // - a line inval caused by a cache miss
4891                                        // - a processor XTN inval request,
4892                                        // - a WRITE hit,
4893                                        // - a Dirty bit update
4894                                        // Input arguments are:
4895                                        // - r_dcache_tlb_inval_line
4896                                        // - r_dcache_tlb_inval_set
4897                                        // - r_dcache_fsm_scan_save
4898    {
4899        paddr_t line = r_dcache_tlb_inval_line.read();
4900        size_t  set  = r_dcache_tlb_inval_set.read();
4901        size_t  way;
4902        bool    ok;
4903
4904        for ( way = 0 ; way < m_itlb_ways ; way++ )
4905        {
4906            ok = r_itlb.inval( line, way, set );
4907
4908#if DEBUG_DCACHE
4909if ( m_debug_activated and ok )
4910{
4911    std::cout << "  <PROC " << name()
4912              << ".DCACHE_INVAL_TLB_SCAN> Invalidate ITLB entry:" << std::hex
4913              << " line = " << line << std::dec
4914              << " / set = " << set
4915              << " / way = " << way << std::endl;
4916}
4917#endif
4918        }
4919
4920        for ( way = 0 ; way < m_dtlb_ways ; way++ )
4921        {
4922            ok = r_dtlb.inval( line, way, set );
4923
4924#if DEBUG_DCACHE
4925if ( m_debug_activated and ok )
4926std::cout << "  <PROC " << name() << " DCACHE_INVAL_TLB_SCAN>"
4927          << " Invalidate DTLB entry" << std::hex
4928          << " / line = " << line << std::dec
4929          << " / set = " << set
4930          << " / way = " << way << std::endl;
4931#endif
4932        }
4933
4934        // return to the calling state when TLB inval completed
4935        if ( r_dcache_tlb_inval_set.read() == (m_dtlb_sets-1) )
4936        {
4937            r_dcache_fsm = r_dcache_fsm_scan_save.read();
4938        }
4939        r_dcache_tlb_inval_set = r_dcache_tlb_inval_set.read() + 1;
4940        break;
4941    }
4942    } // end switch r_dcache_fsm
4943
4944    ///////////////// wbuf update ///////////////////////////////////////////////////////
4945    r_wbuf.update();
4946
4947    ///////////////// llsc update ///////////////////////////////////////////////////////
4948    if (r_dcache_llsc_valid.read()) r_dcache_llsc_count = r_dcache_llsc_count.read() - 1;
4949    if (r_dcache_llsc_count.read() == 1) r_dcache_llsc_valid = false;
4950
4951    //////////////// test processor frozen //////////////////////////////////////////////
4952    // The simulation exit if the number of consecutive frozen cycles
4953    // is larger than the m_max_frozen_cycles (constructor parameter)
4954    if ( (m_ireq.valid and not m_irsp.valid) or (m_dreq.valid and not m_drsp.valid) )
4955    {
4956        m_cpt_frz_cycles++;             // used for instrumentation
4957        m_cpt_stop_simulation++;        // used for debug
4958        if ( m_cpt_stop_simulation > m_max_frozen_cycles )
4959        {
4960            std::cout << std::dec << "ERROR in CC_VCACHE_WRAPPER " << name() << std::endl
4961                      << " stop at cycle " << m_cpt_total_cycles << std::endl
4962                      << " frozen since cycle " << m_cpt_total_cycles - m_max_frozen_cycles
4963                      << std::endl;
4964                      r_iss.dump();
4965            exit(1);
4966        }
4967    }
4968    else
4969    {
4970        m_cpt_stop_simulation = 0;
4971    }
4972
4973    /////////// execute one iss cycle /////////////////////////////////
4974    {
4975    uint32_t it = 0;
4976    for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if(p_irq[i].read()) it |= (1<<i);
4977    r_iss.executeNCycles(1, m_irsp, m_drsp, it);
4978    }
4979
4980    ////////////////////////////////////////////////////////////////////////////
4981    // The VCI_CMD FSM controls the following ressources:
4982    // - r_vci_cmd_fsm
4983    // - r_vci_cmd_min
4984    // - r_vci_cmd_max
4985    // - r_vci_cmd_cpt
4986    // - r_vci_cmd_imiss_prio
4987    // - wbuf (reset)
4988    // - r_icache_miss_req (reset)
4989    // - r_icache_unc_req (reset)
4990    // - r_dcache_vci_miss_req (reset)
4991    // - r_dcache_vci_unc_req (reset)
4992    // - r_dcache_vci_ll_req (reset)
4993    // - r_dcache_vci_sc_req (reset in case of local sc fail)
4994    // - r_dcache_vci_cas_req (reset)
4995    //
4996    // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
4997    // There are 8 request types, with the following priorities :
4998    // 1 - Data Read Miss         : r_dcache_vci_miss_req and miss in the write buffer
4999    // 2 - Data Read Uncachable   : r_dcache_vci_unc_req
5000    // 3 - Instruction Miss       : r_icache_miss_req and miss in the write buffer
5001    // 4 - Instruction Uncachable : r_icache_unc_req
5002    // 5 - Data Write             : r_wbuf.rok()
5003    // 6 - Data Linked Load       : r_dcache_vci_ll_req
5004    // 7 - Data Store Conditionnal: r_dcache_vci_sc_req
5005    // 8 - Compare And Swap       : r_dcache_vci_cas_req
5006    //
5007    // As we want to support several simultaneous VCI transactions, the VCI_CMD_FSM
5008    // and the VCI_RSP_FSM are fully desynchronized.
5009    //
5010    // VCI formats:
5011    // According to the VCI advanced specification, all read requests packets
5012    // (data Uncached, Miss data, instruction Uncached, Miss instruction)
5013    // are one word packets.
5014    // For write burst packets, all words are in the same cache line,
5015    // and addresses must be contiguous (the BE field is 0 in case of "holes").
5016    // The sc command packet implements actually a compare-and-swap mechanism
5017    // and the packet contains two flits.
5018    ////////////////////////////////////////////////////////////////////////////////////
5019
5020
5021    switch ( r_vci_cmd_fsm.read() )
5022    {
5023        //////////////
5024        case CMD_IDLE:
5025        {
5026            // DCACHE read requests (r_dcache_vci_miss_req or r_dcache_vci_ll_req), and
5027            // ICACHE read requests (r_icache_miss_req) require both a write_buffer access
5028            // to check a possible pending write on the same cache line.
5029            // As there is only one possible access per cycle to write buffer, we implement
5030            // a round-robin priority between DCACHE and ICACHE for this access,
5031            // using the r_vci_cmd_imiss_prio flip-flop.
5032
5033            size_t      wbuf_min;
5034            size_t      wbuf_max;
5035
5036            bool dcache_unc_req = r_dcache_vci_unc_req.read() and
5037                 ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() );
5038
5039            bool dcache_miss_req = r_dcache_vci_miss_req.read() and
5040                 ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() );
5041
5042            bool dcache_ll_req   = r_dcache_vci_ll_req.read() and
5043                 ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() );
5044
5045            bool icache_miss_req = r_icache_miss_req.read() and
5046                 ( not (r_dcache_vci_miss_req.read() or
5047                        r_dcache_vci_ll_req.read() or
5048                        r_dcache_vci_unc_req.read())
5049                     or r_vci_cmd_imiss_prio.read() );
5050
5051            // 1 - Data Read Miss
5052            if ( dcache_miss_req and r_wbuf.miss(r_dcache_vci_paddr.read()) )
5053            {
5054                r_vci_cmd_fsm         = CMD_DATA_MISS;
5055                r_dcache_vci_miss_req = false;
5056                r_vci_cmd_imiss_prio  = true;
5057//                m_cpt_dmiss_transaction++;
5058            }
5059            // 2 - Data Read Uncachable
5060            else if ( dcache_unc_req and r_wbuf.miss(r_dcache_vci_paddr.read()))
5061            {
5062                r_vci_cmd_fsm        = CMD_DATA_UNC;
5063                r_dcache_vci_unc_req = false;
5064//                m_cpt_dunc_transaction++;
5065            }
5066            // 3 - Data Linked Load
5067            else if ( dcache_ll_req and r_wbuf.miss(r_dcache_vci_paddr.read()))
5068            {
5069                r_dcache_vci_ll_req = false;
5070                r_vci_cmd_fsm       = CMD_DATA_LL;
5071//              m_cpt_ll_transaction++;
5072            }
5073            // 4 - Instruction Miss
5074            else if ( icache_miss_req and r_wbuf.miss(r_icache_vci_paddr.read()) )
5075            {
5076                r_vci_cmd_fsm        = CMD_INS_MISS;
5077                r_icache_miss_req    = false;
5078                r_vci_cmd_imiss_prio = false;
5079//                m_cpt_imiss_transaction++;
5080            }
5081            // 5 - Instruction Uncachable
5082            else if ( r_icache_unc_req.read() )
5083            {
5084                r_vci_cmd_fsm       = CMD_INS_UNC;
5085                r_icache_unc_req    = false;
5086//                m_cpt_iunc_transaction++;
5087            }
5088            // 6 - Data Write
5089            else if ( r_wbuf.rok(&wbuf_min, &wbuf_max) )
5090            {
5091                r_vci_cmd_fsm       = CMD_DATA_WRITE;
5092                r_vci_cmd_cpt       = wbuf_min;
5093                r_vci_cmd_min       = wbuf_min;
5094                r_vci_cmd_max       = wbuf_max;
5095//                m_cpt_write_transaction++;
5096//                m_length_write_transaction += (wbuf_max-wbuf_min+1);
5097            }
5098            // 7 - Data Store Conditionnal
5099            else if ( r_dcache_vci_sc_req.read() )
5100            {
5101                r_dcache_vci_sc_req = false;
5102                r_vci_cmd_cpt  = 0;
5103                r_vci_cmd_fsm  = CMD_DATA_SC;
5104//              m_cpt_sc_transaction++;
5105            }
5106            // 8 - Compare And Swap
5107            else if ( r_dcache_vci_cas_req.read() )
5108            {
5109                r_vci_cmd_fsm        = CMD_DATA_CAS;
5110                r_dcache_vci_cas_req = false;
5111                r_vci_cmd_cpt        = 0;
5112//              m_cpt_cas_transaction++;
5113            }
5114
5115#if DEBUG_CMD
5116if ( m_debug_activated )
5117{
5118std::cout << "  <PROC " << name() << " CMD_IDLE>"
5119          << " / dmiss_req = " << dcache_miss_req
5120          << " / imiss_req = " << icache_miss_req
5121          << std::endl;
5122}
5123#endif
5124            break;
5125        }
5126        ////////////////////
5127        case CMD_DATA_WRITE:
5128        {
5129            if ( p_vci.cmdack.read() )
5130            {
5131                r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
5132                if (r_vci_cmd_cpt == r_vci_cmd_max) // last flit sent
5133                {
5134                    r_vci_cmd_fsm = CMD_IDLE ;
5135                    r_wbuf.sent() ;
5136                }
5137            }
5138            break;
5139        }
5140        /////////////////
5141        case CMD_DATA_SC:
5142        case CMD_DATA_CAS:
5143        {
5144            // The CAS and SC VCI commands contain two flits
5145            if ( p_vci.cmdack.read() )
5146            {
5147               r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
5148               if (r_vci_cmd_cpt == 1) r_vci_cmd_fsm = CMD_IDLE ;
5149            }
5150            break;
5151        }
5152        //////////////////
5153        case CMD_INS_MISS:
5154        case CMD_INS_UNC:
5155        case CMD_DATA_MISS:
5156        case CMD_DATA_UNC:
5157        case CMD_DATA_LL:
5158        {
5159            // all read VCI commands contain one single flit
5160            if ( p_vci.cmdack.read() ) {
5161                r_vci_cmd_fsm = CMD_IDLE;
5162            }
5163            break;
5164        }
5165
5166    } // end  switch r_vci_cmd_fsm
5167
5168    //////////////////////////////////////////////////////////////////////////
5169    // The VCI_RSP FSM controls the following ressources:
5170    // - r_vci_rsp_fsm:
5171    // - r_vci_rsp_fifo_icache (push)
5172    // - r_vci_rsp_fifo_dcache (push)
5173    // - r_vci_rsp_data_error (set)
5174    // - r_vci_rsp_ins_error (set)
5175    // - r_vci_rsp_cpt
5176    // - r_dcache_vci_sc_req (reset when SC response recieved)
5177    //
5178    // As the VCI_RSP and VCI_CMD are fully desynchronized to support several
5179    // simultaneous VCI transactions, this FSM uses the VCI RPKTID field
5180    // to identify the transactions.
5181    //
5182    // VCI vormat:
5183    // This component checks the response packet length and accepts only
5184    // single word packets for write response packets.
5185    //
5186    // Error handling:
5187    // This FSM analyzes the VCI error code and signals directly the Write Bus Error.
5188    // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error
5189    // flip_flop and the error is signaled by the DCACHE FSM.
5190    // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
5191    // flip_flop and the error is signaled by the ICACHE FSM.
5192    // In case of Cleanup Error, the simulation stops with an error message...
5193    //////////////////////////////////////////////////////////////////////////
5194
5195    switch ( r_vci_rsp_fsm.read() )
5196    {
5197    //////////////
5198    case RSP_IDLE:
5199    {
5200        if ( p_vci.rspval.read() )
5201        {
5202            r_vci_rsp_cpt = 0;
5203
5204            if      ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_DATA_UNC  )
5205            {
5206                r_vci_rsp_fsm = RSP_DATA_UNC;
5207            }
5208            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_DATA_MISS )
5209            {
5210                r_vci_rsp_fsm = RSP_DATA_MISS;
5211            }
5212            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_INS_UNC   )
5213            {
5214                r_vci_rsp_fsm = RSP_INS_UNC;
5215            }
5216            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_INS_MISS  )
5217            {
5218                r_vci_rsp_fsm = RSP_INS_MISS;
5219            }
5220            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_WRITE          )
5221            {
5222                r_vci_rsp_fsm = RSP_DATA_WRITE;
5223            }
5224            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_CAS            )
5225            {
5226                r_vci_rsp_fsm = RSP_DATA_UNC;
5227            }
5228            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_LL             )
5229            {
5230                r_vci_rsp_fsm = RSP_DATA_LL;
5231            }
5232            else if ( (p_vci.rpktid.read() & 0x7) == TYPE_SC             )
5233            {
5234                r_vci_rsp_fsm = RSP_DATA_UNC;
5235            }
5236            else
5237            {
5238                assert(false and "Unexpected VCI response");
5239            }
5240        }
5241        break;
5242    }
5243        //////////////////
5244        case RSP_INS_MISS:
5245        {
5246            if ( p_vci.rspval.read() )
5247            {
5248                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5249                {
5250                    r_vci_rsp_ins_error = true;
5251                    if ( p_vci.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
5252                }
5253                else                                        // no error reported
5254                {
5255                    if ( r_vci_rsp_fifo_icache.wok() )
5256                    {
5257                        assert( (r_vci_rsp_cpt.read() < m_icache_words) and
5258                        "The VCI response packet for instruction miss is too long" );
5259
5260                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
5261                        vci_rsp_fifo_icache_put       = true,
5262                        vci_rsp_fifo_icache_data      = p_vci.rdata.read();
5263                        if ( p_vci.reop.read() )
5264                        {
5265                            assert( (r_vci_rsp_cpt.read() == m_icache_words - 1) and
5266                            "The VCI response packet for instruction miss is too short");
5267
5268                            r_vci_rsp_fsm    = RSP_IDLE;
5269                        }
5270                    }
5271                }
5272            }
5273            break;
5274        }
5275        /////////////////
5276        case RSP_INS_UNC:
5277        {
5278            if (p_vci.rspval.read() )
5279            {
5280                assert( p_vci.reop.read() and
5281                "illegal VCI response packet for uncachable instruction");
5282
5283                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5284                {
5285                    r_vci_rsp_ins_error = true;
5286                    r_vci_rsp_fsm = RSP_IDLE;
5287                }
5288                else                                         // no error reported
5289                {
5290                    if ( r_vci_rsp_fifo_icache.wok())
5291                    {
5292                        vci_rsp_fifo_icache_put       = true;
5293                        vci_rsp_fifo_icache_data      = p_vci.rdata.read();
5294                        r_vci_rsp_fsm = RSP_IDLE;
5295                    }
5296                }
5297            }
5298            break;
5299        }
5300        ///////////////////
5301        case RSP_DATA_MISS:
5302        {
5303            if ( p_vci.rspval.read() )
5304            {
5305                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5306                {
5307                    r_vci_rsp_data_error = true;
5308                    if ( p_vci.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
5309                }
5310                else                                        // no error reported
5311                {
5312                    if ( r_vci_rsp_fifo_dcache.wok() )
5313                    {
5314                        assert( (r_vci_rsp_cpt.read() < m_dcache_words) and
5315                        "The VCI response packet for data miss is too long");
5316
5317                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
5318                        vci_rsp_fifo_dcache_put       = true,
5319                        vci_rsp_fifo_dcache_data      = p_vci.rdata.read();
5320                        if ( p_vci.reop.read() )
5321                        {
5322                            assert( (r_vci_rsp_cpt.read() == m_dcache_words - 1) and
5323                            "The VCI response packet for data miss is too short");
5324
5325                            r_vci_rsp_fsm     = RSP_IDLE;
5326                        }
5327                    }
5328                }
5329            }
5330            break;
5331        }
5332        //////////////////
5333        case RSP_DATA_UNC:
5334        {
5335            if (p_vci.rspval.read() )
5336            {
5337                assert( p_vci.reop.read() and
5338                "illegal VCI response packet for uncachable read data");
5339
5340                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5341                {
5342                    r_vci_rsp_data_error = true;
5343                    r_vci_rsp_fsm = RSP_IDLE;
5344                }
5345                else                                         // no error reported
5346                {
5347                    if ( r_vci_rsp_fifo_dcache.wok())
5348                    {
5349                        vci_rsp_fifo_dcache_put       = true;
5350                        vci_rsp_fifo_dcache_data      = p_vci.rdata.read();
5351                        r_vci_rsp_fsm = RSP_IDLE;
5352                    }
5353                }
5354            }
5355            break;
5356        }
5357        /////////////////
5358        case RSP_DATA_LL:
5359        {
5360            if ( p_vci.rspval.read() )
5361            {
5362                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5363                {
5364                    r_vci_rsp_data_error = true;
5365                    r_vci_rsp_fsm = RSP_IDLE;
5366                    break;
5367                }
5368                if (r_vci_rsp_cpt.read() == 0) //first flit
5369                {
5370                    if(r_vci_rsp_fifo_dcache.wok())
5371                    {
5372                        assert(!p_vci.reop.read() &&
5373                            "illegal VCI response packet for LL");
5374                        vci_rsp_fifo_dcache_put  = true;
5375                        vci_rsp_fifo_dcache_data = p_vci.rdata.read();
5376                        r_vci_rsp_cpt            = r_vci_rsp_cpt.read() + 1;
5377                    }
5378                    break;
5379                }
5380                else // last flit
5381                {
5382                    if(r_vci_rsp_fifo_dcache.wok())
5383                    {
5384                        assert(p_vci.reop.read() &&
5385                            "illegal VCI response packet for LL");
5386                        vci_rsp_fifo_dcache_put  = true;
5387                        vci_rsp_fifo_dcache_data = p_vci.rdata.read();
5388                        r_vci_rsp_fsm            = RSP_IDLE;
5389                    }
5390                    break;
5391                }
5392            }
5393            break;
5394        }
5395        ////////////////////
5396        case RSP_DATA_WRITE:
5397        {
5398            if (p_vci.rspval.read())
5399            {
5400                assert( p_vci.reop.read() and
5401                "a VCI response packet must contain one flit for a write transaction");
5402
5403                r_vci_rsp_fsm = RSP_IDLE;
5404                uint32_t   wbuf_index = p_vci.rtrdid.read();
5405                bool       cacheable  = r_wbuf.completed(wbuf_index);
5406                if ( not cacheable ) r_dcache_pending_unc_write = false;
5407                if ( (p_vci.rerror.read()&0x1) != 0 ) r_iss.setWriteBerr();
5408            }
5409            break;
5410        }
5411    } // end switch r_vci_rsp_fsm
5412
5413    /////////////////////////////////////////////////////////////////////////////////////
5414    // The CC_SEND FSM is in charge of sending cleanups and the multicast
5415    // acknowledgements on the coherence network. It has two clients (DCACHE FSM
5416    // and ICACHE FSM) that are served with a round-robin priority.
5417    // The CC_SEND FSM resets the r_*cache_cc_send_req request flip-flops as
5418    // soon as the request has been sent.
5419    /////////////////////////////////////////////////////////////////////////////////////
5420    switch ( r_cc_send_fsm.read() )
5421    {
5422        ///////////////////////////
5423        case CC_SEND_IDLE:
5424        {
5425            ///////////////////////////////////////////////////////
5426            // handling round robin between icache and dcache :  //
5427            // we first check for the last client and listen for //
5428            // a request of the other, then update the client    //
5429            // r_cc_send_last_client : 0 dcache / 1 icache
5430            ///////////////////////////////////////////////////////
5431            bool update_last_client = r_cc_send_last_client.read();
5432            if ( r_cc_send_last_client.read() == 0 ) // last client was dcache
5433            {
5434                if (r_icache_cc_send_req.read()) // request from icache
5435                    update_last_client = 1; // update last client to icache
5436            }
5437            else // last client was icache
5438            {
5439                if (r_dcache_cc_send_req.read()) // request from dcache
5440                    update_last_client = 0; // update last client to dcache
5441            }
5442            r_cc_send_last_client = update_last_client;
5443
5444            // if there is an actual request
5445            if (r_dcache_cc_send_req.read() or r_icache_cc_send_req.read())
5446            {
5447                // the new client is dcache and has a cleanup request
5448                if      ( (update_last_client == 0) and
5449                          (r_dcache_cc_send_type.read() == CC_TYPE_CLEANUP))
5450                    r_cc_send_fsm = CC_SEND_CLEANUP_1;
5451                // the new client is dcache and has a multi acknowledgement request
5452                else if ( (update_last_client == 0) and
5453                          (r_dcache_cc_send_type.read() == CC_TYPE_MULTI_ACK))
5454                    r_cc_send_fsm = CC_SEND_MULTI_ACK;
5455                // the new client is icache and has a cleanup request
5456                else if ( (update_last_client == 1) and
5457                          (r_icache_cc_send_type.read() == CC_TYPE_CLEANUP))
5458                    r_cc_send_fsm = CC_SEND_CLEANUP_1;
5459                // the new client is icache and has a multi acknowledgement request
5460                else if ( (update_last_client == 1) and
5461                        (r_icache_cc_send_type.read() == CC_TYPE_MULTI_ACK))
5462                    r_cc_send_fsm = CC_SEND_MULTI_ACK;
5463            }
5464            break;
5465        }
5466        ///////////////////////////
5467        case CC_SEND_CLEANUP_1:
5468        {
5469            // wait for the first flit to be consumed
5470            if (p_dspin_p2m.read.read())
5471                r_cc_send_fsm = CC_SEND_CLEANUP_2;
5472
5473            break;
5474        }
5475        ///////////////////////////
5476        case CC_SEND_CLEANUP_2:
5477        {
5478            // wait for the second flit to be consumed
5479            if (p_dspin_p2m.read.read())
5480            {
5481                if (r_cc_send_last_client.read() == 0) // dcache active request
5482                    r_dcache_cc_send_req = false; // reset dcache request
5483                else // icache active request
5484                    r_icache_cc_send_req = false; // reset icache request
5485
5486                // go back to idle state
5487                r_cc_send_fsm = CC_SEND_IDLE;
5488            }
5489            break;
5490        }
5491        ///////////////////////////
5492        case CC_SEND_MULTI_ACK:
5493        {
5494            // wait for the flit to be consumed
5495            if(p_dspin_p2m.read.read())
5496            {
5497                if(r_cc_send_last_client.read() == 0) // dcache active request
5498                    r_dcache_cc_send_req = false; // reset dcache request
5499                else // icache active request
5500                    r_icache_cc_send_req = false; // reset icache request
5501                // go back to idle state
5502                r_cc_send_fsm = CC_SEND_IDLE;
5503            }
5504            break;
5505        }
5506    } // end switch CC_SEND FSM
5507
5508    ///////////////////////////////////////////////////////////////////////////////
5509    //  CC_RECEIVE  FSM
5510    // This FSM receive all coherence packets on a DSPIN40 port.
5511    // There is 5 packet types:
5512    // - CC_DATA_INVAL : DCACHE invalidate request
5513    // - CC_DATA_UPDT  : DCACHE update request (multi-words)
5514    // - CC_INST_INVAL : ICACHE invalidate request
5515    // - CC_INST_UPDT  : ICACHE update request (multi-words)
5516    // - CC_BROADCAST  : Broadcast invalidate request (both DCACHE & ICACHE)
5517    //////////////////////////////////////////////////////////////////////////////
5518    switch( r_cc_receive_fsm.read() )
5519    {
5520        /////////////////////
5521        case CC_RECEIVE_IDLE:
5522        {
5523            // a coherence request has arrived
5524            if (p_dspin_m2p.write.read())
5525            {
5526                // initialize dspin received data
5527                uint64_t receive_data = p_dspin_m2p.data.read();
5528                // initialize coherence packet type
5529                uint64_t receive_type = DspinDhccpParam::dspin_get(receive_data,
5530                                            DspinDhccpParam::M2P_TYPE);
5531                // test for a broadcast
5532                if (DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::M2P_BC))
5533                {
5534                    r_cc_receive_fsm = CC_RECEIVE_BRDCAST_HEADER;
5535                }
5536                // test for a multi updt
5537                else if (receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_DATA) 
5538                {
5539                    r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_HEADER;
5540                }
5541                else if (receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_INST)
5542                {
5543                    r_cc_receive_fsm = CC_RECEIVE_INS_UPDT_HEADER;
5544                }
5545                // test for a multi inval
5546                else if (receive_type == DspinDhccpParam::TYPE_MULTI_INVAL_DATA)
5547                {
5548                    r_cc_receive_fsm = CC_RECEIVE_DATA_INVAL_HEADER;
5549                }
5550                else
5551                {
5552                    r_cc_receive_fsm = CC_RECEIVE_INS_INVAL_HEADER;
5553                }
5554            }
5555            break;
5556        }
5557        ///////////////////////////////
5558        case CC_RECEIVE_BRDCAST_HEADER:
5559        {
5560            // no actual data in the HEADER, just skip to second flit
5561            r_cc_receive_fsm = CC_RECEIVE_BRDCAST_NLINE;
5562            break;
5563        }
5564        //////////////////////////////
5565        case CC_RECEIVE_BRDCAST_NLINE:
5566        {
5567            // initialize dspin received data
5568            uint64_t receive_data = p_dspin_m2p.data.read();
5569            // wait for both dcache and icache to take the request
5570            // TODO maybe we need to wait for both only to leave the state, but
5571            // not to actually post a request to an available cache => need a
5572            // flip_flop to check that ?
5573            if (not (r_cc_receive_icache_req.read()) and
5574                not (r_cc_receive_dcache_req.read()) and
5575                (p_dspin_m2p.write.read()))
5576            {
5577                // request dcache to handle the BROADCAST
5578                r_cc_receive_dcache_req = true;
5579                r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,
5580                                             DspinDhccpParam::BROADCAST_NLINE);
5581                r_cc_receive_dcache_type = CC_TYPE_INVAL;
5582                // request icache to handle the BROADCAST
5583                r_cc_receive_icache_req = true;
5584                r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,
5585                                             DspinDhccpParam::BROADCAST_NLINE);
5586                r_cc_receive_icache_type = CC_TYPE_INVAL;
5587                // get back to idle state
5588                r_cc_receive_fsm = CC_RECEIVE_IDLE;
5589                break;
5590            }
5591            // keep waiting for the caches to accept the request
5592            break;
5593        }
5594        /////////////////////////////
5595        case CC_RECEIVE_DATA_INVAL_HEADER:
5596        {
5597            // sample updt tab index in the HEADER, then skip to second flit
5598            r_cc_receive_fsm = CC_RECEIVE_DATA_INVAL_NLINE;
5599            break;
5600        }
5601        /////////////////////////////
5602        case CC_RECEIVE_INS_INVAL_HEADER:
5603        {
5604            // sample updt tab index in the HEADER, then skip to second flit
5605            r_cc_receive_fsm = CC_RECEIVE_INS_INVAL_NLINE;
5606            break;
5607        }
5608        ////////////////////////////
5609        case CC_RECEIVE_DATA_INVAL_NLINE:
5610        {
5611            // sample nline in the second flit
5612            uint64_t receive_data = p_dspin_m2p.data.read();
5613            // for data INVAL, wait for dcache to take the request
5614            if (p_dspin_m2p.write.read() and not r_cc_receive_dcache_req.read())
5615            {
5616                // request dcache to handle the INVAL
5617                r_cc_receive_dcache_req = true;
5618                r_cc_receive_dcache_nline = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
5619                r_cc_receive_dcache_type = CC_TYPE_INVAL;
5620                // get back to idle state
5621                r_cc_receive_fsm = CC_RECEIVE_IDLE;
5622                break;
5623            }
5624            break;
5625        }
5626        //////////////////////////////
5627        case CC_RECEIVE_INS_INVAL_NLINE:
5628        {
5629            // sample nline in the second flit
5630            uint64_t receive_data = p_dspin_m2p.data.read();
5631            // for ins INVAL, wait for icache to take the request
5632            if (p_dspin_m2p.write.read() and not r_cc_receive_icache_req.read())
5633            {
5634                // request icache to handle the INVAL
5635                r_cc_receive_icache_req = true;
5636                r_cc_receive_icache_nline = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
5637                r_cc_receive_icache_type = CC_TYPE_INVAL;
5638                // get back to idle state
5639                r_cc_receive_fsm = CC_RECEIVE_IDLE;
5640                break;
5641            }
5642            break;
5643        }
5644        ////////////////////////////
5645        case CC_RECEIVE_DATA_UPDT_HEADER:
5646        {
5647            // sample updt tab index in the HEADER, than skip to second flit
5648            uint64_t receive_data = p_dspin_m2p.data.read();
5649            // for data INVAL, wait for dcache to take the request and fifo to
5650            // be empty
5651            if (not r_cc_receive_dcache_req.read())
5652            {
5653                r_cc_receive_dcache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
5654                r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_NLINE;
5655                break;
5656            }
5657            break;
5658        }
5659        ////////////////////////////
5660        case CC_RECEIVE_INS_UPDT_HEADER:
5661        {
5662            // sample updt tab index in the HEADER, than skip to second flit
5663            uint64_t receive_data = p_dspin_m2p.data.read();
5664            // for ins INVAL, wait for icache to take the request and fifo to be
5665            // empty
5666            if (not r_cc_receive_icache_req.read())
5667            {
5668                r_cc_receive_icache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
5669                r_cc_receive_fsm = CC_RECEIVE_INS_UPDT_NLINE;
5670                break;
5671            }
5672            // keep waiting for the correct cache to accept the request
5673            break;
5674        }
5675        ///////////////////////////
5676        case CC_RECEIVE_DATA_UPDT_NLINE:
5677        {
5678            // sample nline and word index in the second flit
5679            uint64_t receive_data = p_dspin_m2p.data.read();
5680            // for data INVAL, wait for dcache to take the request and fifo to
5681            // be empty
5682            if ( r_cc_receive_updt_fifo_be.empty() and
5683                 p_dspin_m2p.write.read() )
5684            {
5685                r_cc_receive_dcache_req = true;
5686                r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_NLINE);
5687                r_cc_receive_word_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
5688                r_cc_receive_dcache_type = CC_TYPE_UPDT;
5689                // get back to idle state
5690                r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_DATA;
5691                break;
5692            }
5693            break;
5694        }
5695        ////////////////////////////
5696        case CC_RECEIVE_INS_UPDT_NLINE:
5697        {
5698            // sample nline and word index in the second flit
5699            uint64_t receive_data = p_dspin_m2p.data.read();
5700            // for ins INVAL, wait for icache to take the request and fifo to be
5701            // empty
5702            if ( r_cc_receive_updt_fifo_be.empty() and
5703                 p_dspin_m2p.write.read() )
5704            {
5705                r_cc_receive_icache_req = true;
5706                r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_NLINE);
5707                r_cc_receive_word_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
5708                r_cc_receive_icache_type = CC_TYPE_UPDT;
5709                // get back to idle state
5710                r_cc_receive_fsm = CC_RECEIVE_INS_UPDT_DATA;
5711                break;
5712            }
5713            break;
5714        }
5715        //////////////////////////
5716        case CC_RECEIVE_DATA_UPDT_DATA:
5717        {
5718            // wait for the fifo
5719            if (r_cc_receive_updt_fifo_be.wok() and (p_dspin_m2p.write.read()))
5720            {
5721                uint64_t receive_data = p_dspin_m2p.data.read();
5722                bool     receive_eop  = p_dspin_m2p.eop.read();
5723                cc_receive_updt_fifo_be   = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_BE);
5724                cc_receive_updt_fifo_data = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_DATA);
5725                cc_receive_updt_fifo_eop  = receive_eop;
5726                cc_receive_updt_fifo_put  = true;
5727                if ( receive_eop ) r_cc_receive_fsm = CC_RECEIVE_IDLE;
5728            }
5729            break;
5730        }
5731        //////////////////////////
5732        case CC_RECEIVE_INS_UPDT_DATA:
5733        {
5734            // wait for the fifo
5735            if (r_cc_receive_updt_fifo_be.wok() and (p_dspin_m2p.write.read()))
5736            {
5737                uint64_t receive_data = p_dspin_m2p.data.read();
5738                bool     receive_eop  = p_dspin_m2p.eop.read();
5739                cc_receive_updt_fifo_be   = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_BE);
5740                cc_receive_updt_fifo_data = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_DATA);
5741                cc_receive_updt_fifo_eop  = receive_eop;
5742                cc_receive_updt_fifo_put  = true;
5743                if ( receive_eop ) r_cc_receive_fsm = CC_RECEIVE_IDLE;
5744            }
5745            break;
5746        }
5747
5748    } // end switch CC_RECEIVE FSM
5749
5750    ///////////////// DSPIN CLACK interface ///////////////
5751   
5752    uint64_t clack_type = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
5753                                                     DspinDhccpParam::CLACK_TYPE);
5754
5755    size_t clack_way  = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
5756                                                   DspinDhccpParam::CLACK_WAY);
5757
5758    size_t clack_set  = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
5759                                                   DspinDhccpParam::CLACK_SET);
5760
5761    bool dspin_clack_get      = false;
5762    bool dcache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_DATA);
5763    bool icache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_INST);
5764
5765    if (r_dspin_clack_req.read())
5766    {
5767        // CLACK DATA: Send request to DCACHE FSM
5768        if (dcache_clack_request and not r_dcache_clack_req.read()){
5769            r_dcache_clack_req = true;
5770            r_dcache_clack_way = clack_way & ((1ULL<<(uint32_log2(m_dcache_ways)))-1);
5771            r_dcache_clack_set = clack_set & ((1ULL<<(uint32_log2(m_dcache_sets)))-1);
5772            dspin_clack_get    = true;
5773        }
5774
5775        // CLACK INST: Send request to ICACHE FSM
5776        else if (icache_clack_request and not r_icache_clack_req.read()){
5777            r_icache_clack_req = true;
5778            r_icache_clack_way = clack_way & ((1ULL<<(uint32_log2(m_dcache_ways)))-1);
5779            r_icache_clack_set = clack_set & ((1ULL<<(uint32_log2(m_icache_sets)))-1);
5780            dspin_clack_get    = true;
5781        }
5782    }
5783    else
5784    {
5785        dspin_clack_get = true;
5786    }
5787
5788    if (dspin_clack_get)
5789    {
5790        r_dspin_clack_req  = p_dspin_clack.write.read();
5791        r_dspin_clack_flit = p_dspin_clack.data.read();
5792    }
5793
5794    ///////////////// Response FIFOs update  //////////////////////
5795    r_vci_rsp_fifo_icache.update(vci_rsp_fifo_icache_get,
5796                                 vci_rsp_fifo_icache_put,
5797                                 vci_rsp_fifo_icache_data);
5798
5799    r_vci_rsp_fifo_dcache.update(vci_rsp_fifo_dcache_get,
5800                                 vci_rsp_fifo_dcache_put,
5801                                 vci_rsp_fifo_dcache_data);
5802
5803    ///////////////// updt FIFO update  //////////////////////
5804    //TODO check this
5805    r_cc_receive_updt_fifo_be.update(cc_receive_updt_fifo_get,
5806                                 cc_receive_updt_fifo_put,
5807                                 cc_receive_updt_fifo_be);
5808    r_cc_receive_updt_fifo_data.update(cc_receive_updt_fifo_get,
5809                                 cc_receive_updt_fifo_put,
5810                                 cc_receive_updt_fifo_data);
5811    r_cc_receive_updt_fifo_eop.update(cc_receive_updt_fifo_get,
5812                                 cc_receive_updt_fifo_put,
5813                                 cc_receive_updt_fifo_eop);
5814
5815} // end transition()
5816
5817///////////////////////
5818tmpl(void)::genMoore()
5819///////////////////////
5820{
5821
5822    // VCI initiator command on the direct network
5823    // it depends on the CMD FSM state
5824
5825    bool is_sc_or_cas  = (r_vci_cmd_fsm.read() == CMD_DATA_CAS) or
5826                         (r_vci_cmd_fsm.read() == CMD_DATA_SC );
5827
5828    p_vci.pktid  = 0;
5829    p_vci.srcid  = m_srcid;
5830    p_vci.cons   = is_sc_or_cas; 
5831    p_vci.contig = not is_sc_or_cas; 
5832    p_vci.wrap   = false;
5833    p_vci.clen   = 0;
5834    p_vci.cfixed = false;
5835
5836    if ( m_monitor_ok ) {
5837        if ( p_vci.cmdack.read() == true and p_vci.cmdval == true) {
5838            if (((p_vci.address.read()) >= m_monitor_base) and
5839                ((p_vci.address.read()) < m_monitor_base + m_monitor_length) ) {
5840                std::cout << "CC_VCACHE Monitor " << name() << std::hex
5841                          << " Access type = " << vci_cmd_type_str[p_vci.cmd.read()] 
5842                          << " Pktid type = " << vci_pktid_type_str[p_vci.pktid.read()]
5843                          << " : address = " << p_vci.address.read()
5844                          << " / be = " << p_vci.be.read(); 
5845                if ( p_vci.cmd.read() == vci_param::CMD_WRITE ) {
5846                    std::cout << " / data = " << p_vci.wdata.read();
5847                }
5848                std::cout << std::dec << std::endl;
5849            }
5850        }
5851    }
5852
5853    switch ( r_vci_cmd_fsm.read() ) {
5854
5855    case CMD_IDLE:
5856        p_vci.cmdval  = false;
5857        p_vci.address = 0;
5858        p_vci.wdata   = 0;
5859        p_vci.be      = 0;
5860        p_vci.trdid   = 0;
5861        p_vci.pktid   = 0;
5862        p_vci.plen    = 0;
5863        p_vci.cmd     = vci_param::CMD_NOP;
5864        p_vci.eop     = false;
5865        break;
5866
5867    case CMD_INS_MISS:
5868        p_vci.cmdval  = true;
5869        p_vci.address = r_icache_vci_paddr.read() & m_icache_yzmask;
5870        p_vci.wdata   = 0;
5871        p_vci.be      = 0xF;
5872        p_vci.trdid   = 0;
5873        p_vci.pktid   = TYPE_READ_INS_MISS;
5874        p_vci.plen    = m_icache_words<<2;
5875        p_vci.cmd     = vci_param::CMD_READ;
5876        p_vci.eop     = true;
5877        break;
5878
5879    case CMD_INS_UNC:
5880        p_vci.cmdval  = true;
5881        p_vci.address = r_icache_vci_paddr.read() & ~0x3;
5882        p_vci.wdata   = 0;
5883        p_vci.be      = 0xF;
5884        p_vci.trdid   = 0;
5885        p_vci.pktid   = TYPE_READ_INS_UNC;
5886        p_vci.plen    = 4;
5887        p_vci.cmd     = vci_param::CMD_READ;
5888        p_vci.eop     = true;
5889        break;
5890
5891    case CMD_DATA_MISS:
5892        p_vci.cmdval  = true;
5893        p_vci.address = r_dcache_vci_paddr.read() & m_dcache_yzmask;
5894        p_vci.wdata   = 0;
5895        p_vci.be      = 0xF;
5896        p_vci.trdid   = 0;
5897        p_vci.pktid   = TYPE_READ_DATA_MISS;
5898        p_vci.plen    = m_dcache_words << 2;
5899        p_vci.cmd     = vci_param::CMD_READ;
5900        p_vci.eop     = true;
5901        break;
5902
5903    case CMD_DATA_UNC:
5904        p_vci.cmdval  = true;
5905        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
5906        p_vci.wdata   = 0;
5907        p_vci.be      = r_dcache_vci_unc_be.read();
5908        p_vci.trdid   = 0;
5909        p_vci.pktid   = TYPE_READ_DATA_UNC;
5910        p_vci.plen    = 4;
5911        p_vci.cmd     = vci_param::CMD_READ;
5912        p_vci.eop     = true;
5913        break;
5914
5915    case CMD_DATA_WRITE:
5916        p_vci.cmdval  = true;
5917        p_vci.address = r_wbuf.getAddress(r_vci_cmd_cpt.read()) & ~0x3;
5918        p_vci.wdata   = r_wbuf.getData(r_vci_cmd_cpt.read());
5919        p_vci.be      = r_wbuf.getBe(r_vci_cmd_cpt.read());
5920        p_vci.trdid   = r_wbuf.getIndex();
5921        p_vci.pktid   = TYPE_WRITE;
5922        p_vci.plen    = (r_vci_cmd_max.read() - r_vci_cmd_min.read() + 1) << 2;
5923        p_vci.cmd     = vci_param::CMD_WRITE;
5924        p_vci.eop     = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
5925        break;
5926
5927    case CMD_DATA_LL:
5928        p_vci.cmdval  = true;
5929        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
5930        p_vci.wdata   = 0;
5931        p_vci.be      = 0xF;
5932        p_vci.trdid   = 0;
5933        p_vci.pktid   = TYPE_LL;
5934        p_vci.plen    = 8;
5935        p_vci.cmd     = vci_param::CMD_LOCKED_READ;
5936        p_vci.eop     = true;
5937        break;
5938
5939    case CMD_DATA_SC:
5940        p_vci.cmdval  = true;
5941        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
5942        if ( r_vci_cmd_cpt.read() == 0 ) p_vci.wdata = r_dcache_llsc_key.read();
5943        else                             p_vci.wdata = r_dcache_vci_sc_data.read();
5944        p_vci.be      = 0xF;
5945        p_vci.trdid   = 0;
5946        p_vci.pktid   = TYPE_SC;
5947        p_vci.plen    = 8;
5948        p_vci.cmd     = vci_param::CMD_NOP;
5949        p_vci.eop     = (r_vci_cmd_cpt.read() == 1);
5950        break;
5951
5952    case CMD_DATA_CAS:
5953        p_vci.cmdval  = true;
5954        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
5955        if ( r_vci_cmd_cpt.read() == 0 ) p_vci.wdata = r_dcache_vci_cas_old.read();
5956        else                             p_vci.wdata = r_dcache_vci_cas_new.read();
5957        p_vci.be      = 0xF;
5958        p_vci.trdid   = 0;
5959        p_vci.pktid   = TYPE_CAS;
5960        p_vci.plen    = 8;
5961        p_vci.cmd     = vci_param::CMD_NOP;
5962        p_vci.eop     = (r_vci_cmd_cpt.read() == 1);
5963        break;
5964    } // end switch r_vci_cmd_fsm
5965
5966    // VCI initiator response on the direct network
5967    // it depends on the VCI_RSP FSM
5968
5969    switch (r_vci_rsp_fsm.read() )
5970    {
5971        case RSP_DATA_WRITE : p_vci.rspack = true; break;
5972        case RSP_INS_MISS   : p_vci.rspack = r_vci_rsp_fifo_icache.wok(); break;
5973        case RSP_INS_UNC    : p_vci.rspack = r_vci_rsp_fifo_icache.wok(); break;
5974        case RSP_DATA_MISS  : p_vci.rspack = r_vci_rsp_fifo_dcache.wok(); break;
5975        case RSP_DATA_UNC   : p_vci.rspack = r_vci_rsp_fifo_dcache.wok(); break;
5976        case RSP_DATA_LL    : p_vci.rspack = r_vci_rsp_fifo_dcache.wok(); break;
5977        case RSP_IDLE       : p_vci.rspack = false; break;
5978    } // end switch r_vci_rsp_fsm
5979
5980   
5981    // Send coherence packets on DSPIN P2M
5982    // it depends on the CC_SEND FSM
5983
5984    uint64_t dspin_send_data = 0;
5985    switch ( r_cc_send_fsm.read() )
5986    {
5987        //////////////////
5988        case CC_SEND_IDLE:
5989        {
5990            p_dspin_p2m.write = false;
5991            break;
5992        }
5993        ///////////////////////
5994        case CC_SEND_CLEANUP_1:
5995        {
5996            // initialize dspin send data
5997//            DspinDhccpParam::dspin_set(dspin_send_data,
5998//                                       0,
5999//                                       DspinDhccpParam::P2M_EOP);
6000            DspinDhccpParam::dspin_set(dspin_send_data,
6001                                       m_cc_global_id,
6002                                       DspinDhccpParam::CLEANUP_SRCID);
6003            DspinDhccpParam::dspin_set(dspin_send_data,
6004                                       0,
6005                                       DspinDhccpParam::P2M_BC);
6006
6007            if(r_cc_send_last_client.read() == 0) // dcache active request
6008            {
6009                uint64_t dest = (uint64_t) r_dcache_cc_send_nline.read() 
6010                                >> (m_nline_width - m_x_width - m_y_width) 
6011                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
6012 
6013                DspinDhccpParam::dspin_set(dspin_send_data,
6014                                           dest,
6015                                           DspinDhccpParam::CLEANUP_DEST);
6016
6017                DspinDhccpParam::dspin_set(dspin_send_data,
6018                                           (r_dcache_cc_send_nline.read() & 0x300000000ULL)>>32,
6019                                           DspinDhccpParam::CLEANUP_NLINE_MSB);
6020
6021                DspinDhccpParam::dspin_set(dspin_send_data,
6022                                           r_dcache_cc_send_way.read(),
6023                                           DspinDhccpParam::CLEANUP_WAY_INDEX);
6024
6025                DspinDhccpParam::dspin_set(dspin_send_data,
6026                                           DspinDhccpParam::TYPE_CLEANUP_DATA,
6027                                           DspinDhccpParam::P2M_TYPE);
6028            }
6029            else                                // icache active request
6030            {
6031                uint64_t dest = (uint64_t) r_icache_cc_send_nline.read() 
6032                                >> (m_nline_width - m_x_width - m_y_width) 
6033                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
6034
6035                DspinDhccpParam::dspin_set(dspin_send_data,
6036                                           dest,
6037                                           DspinDhccpParam::CLEANUP_DEST);
6038
6039                DspinDhccpParam::dspin_set(dspin_send_data,
6040                                           (r_icache_cc_send_nline.read() & 0x300000000ULL)>>32,
6041                                           DspinDhccpParam::CLEANUP_NLINE_MSB);
6042
6043                DspinDhccpParam::dspin_set(dspin_send_data,
6044                                           r_icache_cc_send_way.read(),
6045                                           DspinDhccpParam::CLEANUP_WAY_INDEX);
6046
6047                DspinDhccpParam::dspin_set(dspin_send_data,
6048                                           DspinDhccpParam::TYPE_CLEANUP_INST,
6049                                           DspinDhccpParam::P2M_TYPE);
6050            }
6051            // send flit
6052            p_dspin_p2m.data  = dspin_send_data;
6053            p_dspin_p2m.write = true;
6054            p_dspin_p2m.eop   = false;
6055            break;
6056        }
6057        ///////////////////////
6058        case CC_SEND_CLEANUP_2:
6059        {
6060            // initialize dspin send data
6061//            DspinDhccpParam::dspin_set(dspin_send_data,
6062//                                       1,
6063//                                       DspinDhccpParam::P2M_EOP);
6064
6065            if(r_cc_send_last_client.read() == 0) // dcache active request
6066            {
6067                DspinDhccpParam::dspin_set(dspin_send_data,
6068                                           r_dcache_cc_send_nline.read() & 0xFFFFFFFFULL,
6069                                           DspinDhccpParam::CLEANUP_NLINE_LSB);
6070            }
6071            else                                  // icache active request
6072            {
6073                DspinDhccpParam::dspin_set(dspin_send_data,
6074                                           r_icache_cc_send_nline.read() & 0xFFFFFFFFULL,
6075                                           DspinDhccpParam::CLEANUP_NLINE_LSB);
6076            }
6077            // send flit
6078            p_dspin_p2m.data  = dspin_send_data;
6079            p_dspin_p2m.write = true;
6080            p_dspin_p2m.eop   = true;
6081            break;
6082        }
6083        ///////////////////////
6084        case CC_SEND_MULTI_ACK:
6085        {
6086            // initialize dspin send data
6087//            DspinDhccpParam::dspin_set(dspin_send_data,
6088//                                       1,
6089//                                       DspinDhccpParam::P2M_EOP);
6090            DspinDhccpParam::dspin_set(dspin_send_data,
6091                                       0,
6092                                       DspinDhccpParam::P2M_BC);
6093            DspinDhccpParam::dspin_set(dspin_send_data,
6094                                       DspinDhccpParam::TYPE_MULTI_ACK,
6095                                       DspinDhccpParam::P2M_TYPE);
6096
6097            if(r_cc_send_last_client.read() == 0) // dcache active request
6098            {
6099                uint64_t dest = (uint64_t) r_dcache_cc_send_nline.read() 
6100                                >> (m_nline_width - m_x_width - m_y_width) 
6101                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
6102 
6103                DspinDhccpParam::dspin_set(dspin_send_data,
6104                                           dest,
6105                                           DspinDhccpParam::MULTI_ACK_DEST);
6106
6107                DspinDhccpParam::dspin_set(dspin_send_data,
6108                                           r_dcache_cc_send_updt_tab_idx.read(),
6109                                           DspinDhccpParam::MULTI_ACK_UPDT_INDEX);
6110            }
6111            else                                    // icache active request
6112            {
6113                uint64_t dest = (uint64_t) r_icache_cc_send_nline.read() 
6114                                >> (m_nline_width - m_x_width - m_y_width) 
6115                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
6116 
6117
6118                DspinDhccpParam::dspin_set(dspin_send_data,
6119                                           dest,
6120                                           DspinDhccpParam::MULTI_ACK_DEST);
6121
6122                DspinDhccpParam::dspin_set(dspin_send_data,
6123                                           r_icache_cc_send_updt_tab_idx.read(),
6124                                           DspinDhccpParam::MULTI_ACK_UPDT_INDEX);
6125            }
6126            // send flit
6127            p_dspin_p2m.data  = dspin_send_data;
6128            p_dspin_p2m.write = true;
6129            p_dspin_p2m.eop   = true;
6130
6131            break;
6132        }
6133    } // end switch CC_SEND FSM
6134
6135    // Receive coherence packets
6136    // It depends on the CC_RECEIVE FSM
6137    switch( r_cc_receive_fsm.read() )
6138    {
6139        /////////////////////
6140        case CC_RECEIVE_IDLE:
6141        {
6142            p_dspin_m2p.read = false;
6143            break;
6144        }
6145        ///////////////////////////////
6146        case CC_RECEIVE_BRDCAST_HEADER:
6147        {
6148            p_dspin_m2p.read = true;
6149            break;
6150        }
6151        //////////////////////////////
6152        case CC_RECEIVE_BRDCAST_NLINE:
6153        {
6154            // TODO maybe we need to wait for both only to leave the state, but
6155            // not to actually post a request to an available cache => need a
6156            // flip_flop to check that ?
6157            if (not (r_cc_receive_icache_req.read()) and not (r_cc_receive_dcache_req.read()))
6158                p_dspin_m2p.read = true;
6159            else
6160                p_dspin_m2p.read = false;
6161            break;
6162        }
6163        /////////////////////////////
6164        case CC_RECEIVE_DATA_INVAL_HEADER:
6165        case CC_RECEIVE_INS_INVAL_HEADER:
6166        {
6167            p_dspin_m2p.read = true;
6168            break;
6169        }
6170        ////////////////////////////
6171        case CC_RECEIVE_DATA_INVAL_NLINE:
6172        {
6173            p_dspin_m2p.read = not r_cc_receive_dcache_req.read();
6174            break;
6175        }
6176        case CC_RECEIVE_INS_INVAL_NLINE:
6177        {
6178            p_dspin_m2p.read = not r_cc_receive_icache_req.read();
6179            break;
6180        }
6181        ///////////////////////////
6182        case CC_RECEIVE_DATA_UPDT_HEADER:
6183        {
6184            if (not r_cc_receive_dcache_req.read())
6185                p_dspin_m2p.read = true;
6186            else
6187                p_dspin_m2p.read = false;
6188            break;
6189        }
6190        ////////////////////////////
6191        case CC_RECEIVE_INS_UPDT_HEADER:
6192        {
6193            if ( not r_cc_receive_icache_req.read()) 
6194                p_dspin_m2p.read = true;
6195            else
6196                p_dspin_m2p.read = false;
6197            break;
6198        }
6199        ///////////////////////////
6200        case CC_RECEIVE_DATA_UPDT_NLINE:
6201        case CC_RECEIVE_INS_UPDT_NLINE:
6202        {
6203            if(r_cc_receive_updt_fifo_be.empty())
6204                p_dspin_m2p.read = true;
6205            else
6206                p_dspin_m2p.read = false;
6207            break;
6208        }
6209        ///////////////////////////
6210        case CC_RECEIVE_DATA_UPDT_DATA:
6211        case CC_RECEIVE_INS_UPDT_DATA:
6212        {
6213            if (r_cc_receive_updt_fifo_be.wok())
6214                p_dspin_m2p.read = true;
6215            else
6216                p_dspin_m2p.read = false;
6217            break;
6218        }
6219    } // end switch CC_RECEIVE FSM
6220
6221
6222    int clack_type = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
6223                                                DspinDhccpParam::CLACK_TYPE);
6224
6225    bool dspin_clack_get      = false;
6226    bool dcache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_DATA);
6227    bool icache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_INST);
6228
6229    if (r_dspin_clack_req.read())
6230    {
6231        // CLACK DATA: wait if pending request to DCACHE FSM
6232        if (dcache_clack_request and not r_dcache_clack_req.read())
6233        {
6234            dspin_clack_get = true;
6235        }
6236
6237        // CLACK INST: wait if pending request to ICACHE FSM
6238        else if (icache_clack_request and not r_icache_clack_req.read())
6239        {
6240            dspin_clack_get = true;
6241        }
6242    }
6243    else
6244    {
6245        dspin_clack_get = true;
6246    }
6247
6248    p_dspin_clack.read = dspin_clack_get; 
6249} // end genMoore
6250
6251tmpl(void)::start_monitor(paddr_t base, paddr_t length)
6252// This version of monitor print both Read and Write request
6253{
6254    m_monitor_ok        = true;
6255    m_monitor_base      = base;
6256    m_monitor_length    = length;
6257}
6258
6259tmpl(void)::stop_monitor()
6260{
6261    m_monitor_ok        = false;
6262}
6263
6264}}
6265
6266// Local Variables:
6267// tab-width: 4
6268// c-basic-offset: 4
6269// c-file-offsets:((innamespace . 0)(inline-open . 0))
6270// indent-tabs-mode: nil
6271// End:
6272
6273// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.