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

Last change on this file since 321 was 321, checked in by joannou, 11 years ago

bugfix in vci_cc_vcache_wrapper_dspin_coherence in coherence type checking

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