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

Last change on this file since 403 was 403, checked in by alain, 11 years ago

Updating vci_cc_vcache_wrapper and vci_mem_cache to comply with the new DSPIN signals (explcit EOP).

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