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

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

Bugfix in vci_cc_vcache_wrapper:

  • The DCACHE FSM must be interruptible by clack and CC request in the XTN_SWITCH state. This is to avoid a deadlock situation between the DCACHE and the ICACHE.

This bug was found in simulation with the next situation:

DCACHE_FSM -> XTN_SWITH state
DCACHE_FSM -> Wait r_dcache_xtn_req to be reset

ICACHE_FSM -> MISS_DIR_UPDT state
ICACHE_FSM -> Wait r_icache_miss_clack to be reset

The ICACHE_FSM only treats the xtn requests in the IDLE state.

The clack to the ICACHE is blocked on the DSPIN port by another
clack to the DCACHE but the DCACHE cannnot treat it as it is
blocked in the XTN_SWITCH state.

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