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

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

Bug fix in the vci_cc_vcache_wrapper and vci_mem_cache components
(and the corresponding dspin coherence versions)

vci_cc_vcache_wrapper:

In the VCI_CMD FSM of the cc_vcache, for the SC command as for the
CAS command, we must set the CONS bit in the VCI packet. In the
same manner we must unset the CONTIG bit in the VCI packet for these
two commands.
These two kind of commands have two flits with the same VCI address.

vci_mem_cache

In the state WRITE_DIR_REQ, we don't have to rewrite the registers
address or word index because they will be assigned with the correct
values in the WRITE_IDLE or WRITE_RSP states.

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