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

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

Merging branch/v5/vci_cc_vcache_wrapper with trunk modifications
to start the development of new coherence protocol modifications
in this component

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