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

Last change on this file since 487 was 487, checked in by haoliu, 11 years ago

Bug fixed in vci_cc_vcache_wrapper component:
1) The r_dcache_paddr_ext is utiliszed in the state DCACHE_XTN_DC_INVAL_VA(DCACHE FSM)
for constructing the physical address when the tlb is not activated.

2) In the ICACHE FSM and DCACHE FSM, the state MISS_SELECT will not be blocked by the
r_icache_cc_send_req (r_dcache_cc_send_req for DCACHE FSM) when a victim solt is found,
because we should assure that the cache L1 can consume the response of the miss read
request when the response has arrived.
(The reason of this condtion comes from a deadlock detected in the above version)

A new filp-flop is utilized in the ICACHE FSM (same in DCACHE FSM) for saving the cleanup victim
request when the r_icache_cc_send_req is true. This saving request will be sent later
in the states MISS_WAIT or MISS_UPDT_DIR when r_icache_cc_send_req is false.

File size: 236.9 KB
Line 
1/* -*- c++ -*-
2 * File : vci_cc_vcache_wrapper.cpp
3 * Copyright (c) UPMC, Lip6, SoC
4 * Authors : Alain GREINER, Yang GAO
5 *
6 * SOCLIB_LGPL_HEADER_BEGIN
7 *
8 * This file is part of SoCLib, GNU LGPLv2.1.
9 *
10 * SoCLib is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; version 2.1 of the License.
13 *
14 * SoCLib is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with SoCLib; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 *
24 * SOCLIB_LGPL_HEADER_END
25 *
26 * Maintainers: cesar.fuguet-tortolero@lip6.fr
27 *              alexandre.joannou@lip6.fr
28 */
29
30#include <cassert>
31#include "arithmetics.h"
32#include "../include/vci_cc_vcache_wrapper.h"
33
34#define DEBUG_DCACHE            1
35#define DEBUG_ICACHE            1
36#define DEBUG_CMD               0
37
38namespace soclib {
39namespace caba {
40
41namespace {
42const char *icache_fsm_state_str[] = {
43        "ICACHE_IDLE",
44
45        "ICACHE_XTN_TLB_FLUSH",
46        "ICACHE_XTN_CACHE_FLUSH",
47        "ICACHE_XTN_CACHE_FLUSH_GO",
48        "ICACHE_XTN_TLB_INVAL",
49        "ICACHE_XTN_CACHE_INVAL_VA",
50        "ICACHE_XTN_CACHE_INVAL_PA",
51        "ICACHE_XTN_CACHE_INVAL_GO",
52
53        "ICACHE_TLB_WAIT",
54
55        "ICACHE_MISS_SELECT",
56        "ICACHE_MISS_CLEAN",
57        "ICACHE_MISS_WAIT",
58        "ICACHE_MISS_DATA_UPDT",
59        "ICACHE_MISS_DIR_UPDT",
60
61        "ICACHE_UNC_WAIT",
62
63        "ICACHE_CC_CHECK",
64        "ICACHE_CC_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        // coherence clack interrupt
1637        if ( r_icache_clack_req.read() )
1638        {
1639            r_icache_fsm = ICACHE_CC_CHECK;
1640            r_icache_fsm_save = r_icache_fsm.read();
1641            break;
1642        }
1643       
1644        // send cleanup victim request
1645        if ( r_icache_cleanup_victim_req.read() and not r_icache_cc_send_req.read() )
1646        {
1647            r_icache_cc_send_req        = true;
1648            r_icache_cc_send_nline      = r_icache_cleanup_victim_nline;
1649            r_icache_cc_send_way        = r_icache_miss_way;
1650            r_icache_cc_send_type       = CC_TYPE_CLEANUP; 
1651            r_icache_cleanup_victim_req = false;
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        // coherence clack interrupt
1726        if ( r_icache_clack_req.read() )
1727        {
1728            r_icache_fsm = ICACHE_CC_CHECK;
1729            r_icache_fsm_save = r_icache_fsm.read();
1730            break;
1731        }
1732
1733        // send cleanup victim request
1734        if ( r_icache_cleanup_victim_req.read() and not r_icache_cc_send_req.read() )
1735        {
1736            r_icache_cc_send_req        = true;
1737            r_icache_cc_send_nline      = r_icache_cleanup_victim_nline;
1738            r_icache_cc_send_way        = r_icache_miss_way;
1739            r_icache_cc_send_type       = CC_TYPE_CLEANUP; 
1740            r_icache_cleanup_victim_req = false;
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( 0,
2006                            r_icache_cc_way.read(),
2007                            r_icache_cc_set.read(),
2008                            CACHE_SLOT_STATE_ZOMBI );
2009
2010        // coherence request completed
2011        r_icache_cc_send_req   = true;
2012        r_icache_cc_send_nline = r_cc_receive_icache_nline.read();
2013        r_icache_cc_send_way   = r_icache_cc_way.read();
2014        r_icache_cc_send_type  = CC_TYPE_CLEANUP;
2015
2016        r_icache_fsm           = r_icache_fsm_save.read();
2017
2018#if DEBUG_ICACHE
2019if ( m_debug_activated )
2020{
2021std::cout << "  <PROC " << name()
2022          << " ICACHE_CC_INVAL> slot returns to ZOMBI state"
2023          << " set = " << r_icache_cc_set.read()
2024          << " / way = " << r_icache_cc_way.read() << std::endl;
2025}
2026#endif
2027
2028        break;
2029    }
2030    ////////////////////
2031    case ICACHE_CC_UPDT:        // hit update : write one word per cycle
2032    {
2033        assert (not r_icache_cc_send_req.read() &&
2034                "ERROR in ICACHE_CC_UPDT: the r_icache_cc_send_req "
2035                "must not be set");
2036
2037        if ( not r_cc_receive_updt_fifo_be.rok() ) break;
2038
2039
2040        size_t  word  = r_icache_cc_word.read();
2041        size_t  way   = r_icache_cc_way.read();
2042        size_t  set   = r_icache_cc_set.read();
2043
2044        if (r_icache_cc_need_write.read())
2045        {
2046            r_icache.write( way,
2047                            set,
2048                            word,
2049                            r_cc_receive_updt_fifo_data.read(),
2050                            r_cc_receive_updt_fifo_be.read() );
2051
2052            r_icache_cc_word = word+1;
2053
2054#ifdef INSTRUMENTATION
2055m_cpt_icache_data_write++;
2056#endif
2057
2058#if DEBUG_ICACHE
2059if ( m_debug_activated )
2060{
2061    std::cout << "  <PROC " << name()
2062              << " ICACHE_CC_UPDT> Write one word "
2063              << " set = " << r_icache_cc_set.read()
2064              << " / way = " << r_icache_cc_way.read()
2065              << " / word = " << r_icache_cc_word.read() << std::endl;
2066}
2067#endif
2068        }
2069
2070        if ( r_cc_receive_updt_fifo_eop.read() )        // last word
2071        {
2072            // no need to write in the cache anymore
2073            r_icache_cc_need_write        = false;
2074
2075            // coherence request completed
2076            r_cc_receive_icache_req       = false;
2077
2078            // request multicast acknowledgement
2079            r_icache_cc_send_req          = true;
2080            r_icache_cc_send_nline        = r_cc_receive_icache_nline.read();
2081            r_icache_cc_send_updt_tab_idx = r_cc_receive_icache_updt_tab_idx.read();
2082            r_icache_cc_send_type         = CC_TYPE_MULTI_ACK;
2083
2084            r_icache_fsm                  = r_icache_fsm_save.read();
2085        }
2086        //consume fifo if not eop
2087        cc_receive_updt_fifo_get  = true;
2088
2089        break;
2090    }
2091
2092    } // end switch r_icache_fsm
2093
2094    ////////////////////////////////////////////////////////////////////////////////////
2095    //      DCACHE FSM
2096    //
2097    // 1/ Coherence operations
2098    //    They are handled as interrupts generated by the CC_RECEIVE FSM.
2099    //    - There is a coherence request when r_tgt_dcache_req is set.
2100    //    They are taken in IDLE, MISS_WAIT, MISS_DIR_UPDT, UNC_WAIT, LL_WAIT
2101    //    and SC_WAIT states.
2102    //    - There is a cleanup acknowledge request when r_cleanup_dcache_req is set.
2103    //    They are taken in IDLE, MISS_SELECT, MISS_CLEAN, MISS_WAIT, MISS_DATA_UPDT,
2104    //    MISS_DIR_UPDT, UNC_WAIT, LL_WAIT, SC_WAIT states.
2105    //    - For both types of requests, actions associated to the pre-empted state
2106    //    are not executed. The DCACHE FSM goes to the proper sub-FSM (CC_CHECK
2107    //    or CC_CLACK) to execute the requested coherence operation, and returns
2108    //    to the pre-empted state.
2109    //
2110    // 2/ TLB miss
2111    //    The page tables are generally cacheable.
2112    //    In case of miss in itlb or dtlb, the tlb miss is handled by a dedicated
2113    //    sub-fsm (DCACHE_TLB_MISS state), that handle possible miss in DCACHE,
2114    //    this sub-fsm implement the table-walk...
2115    //
2116    // 3/ processor requests
2117    //    Processor requests are taken in IDLE state only.
2118    //    The IDLE state implements a two stages pipe-line to handle write bursts:
2119    //    - Both DTLB and DCACHE are accessed in stage P0 (if processor request valid).
2120    //    - The registration in wbuf and the dcache update is done in stage P1
2121    //      (if the processor request is a write).
2122    //    The two r_dcache_wbuf_req and r_dcache_updt_req flip-flops define
2123    //    the operations that must be done in P1 stage, and the access type
2124    //    (read or write) to the DATA part of DCACHE depends on r_dcache_updt_req.
2125    //    READ requests are delayed if a cache update is requested.
2126    //    WRITE or SC requests can require a PTE Dirty bit update (in memory),
2127    //    that is done (before handling the processor request) by a dedicated sub-fsm.
2128    //    If a PTE is modified, both the itlb and dtlb are selectively, but sequencially
2129    //    cleared by a dedicated sub_fsm (DCACHE_INVAL_TLB_SCAN state).
2130    //
2131    // 4/ Atomic instructions LL/SC
2132    //    The LL/SC address are non cacheable (systematic access to memory).
2133    //    The llsc buffer contains a registration for an active LL/SC operation
2134    //    (with an address, a registration key, an aging counter and a valid bit).
2135    //    - LL requests from the processor are transmitted as a one flit VCI command
2136    //      (CMD_LOCKED_READ as CMD, and TYPE_LL as PKTID value). PLEN must
2137    //      be 8 as the response is 2 flits long (data and registration key)
2138    //    - SC requests from the processor are systematically transmitted to the
2139    //      memory cache as 2 flits VCI command (CMD_STORE_COND as CMD, and TYPE_SC
2140    //      as PKTID value).  The first flit contains the registration key, the second
2141    //      flit contains the data to write in case of success.
2142    //      The cache is not updated, as this is done in case of success by the
2143    //      coherence transaction.
2144    //
2145    // 5/ Non cacheable access:
2146    //    This component implement a strong order between non cacheable access
2147    //    (read or write) : A new non cacheable VCI transaction starts only when
2148    //    the previous non cacheable transaction is completed. Both cacheable and
2149    //    non cacheable transactions use the write buffer, but the DCACHE FSM registers
2150    //    a non cacheable write transaction posted in the write buffer by setting the
2151    //    r_dcache_pending_unc_write flip_flop. All other non cacheable requests
2152    //    are stalled until this flip-flop is reset by the VCI_RSP_FSM (when the
2153    //    pending non cacheable write transaction completes).
2154    //
2155    // 6/ Error handling:
2156    //    When the MMU is not activated, Read Bus Errors are synchronous events,
2157    //    but Write Bus Errors are asynchronous events (processor is not frozen).
2158    //    - If a Read Bus Error is detected, the VCI_RSP FSM sets the
2159    //      r_vci_rsp_data_error flip-flop, without writing any data in the
2160    //      r_vci_rsp_fifo_dcache FIFO, and the synchronous error is signaled
2161    //      by the DCACHE FSM.
2162    //    - If a Write Bus Error is detected, the VCI_RSP FSM  signals
2163    //      the asynchronous error using the setWriteBerr() method.
2164    //    When the MMU is activated bus error are rare events, as the MMU
2165    //    checks the physical address before the VCI transaction starts.
2166    ////////////////////////////////////////////////////////////////////////////////////////
2167
2168    // default value for m_drsp
2169    m_drsp.valid = false;
2170    m_drsp.error = false;
2171    m_drsp.rdata = 0;
2172
2173    switch ( r_dcache_fsm.read() )
2174    {
2175    case DCACHE_IDLE: // There are 10 conditions to exit the IDLE state :
2176                      // 1) ITLB/DTLB inval request (update)  => DCACHE_INVAL_TLB_SCAN
2177                      // 2) Coherence request (TGT FSM)       => DCACHE_CC_CHECK
2178                      // 3) ITLB miss request (ICACHE FSM)    => DCACHE_TLB_MISS
2179                      // 4) XTN request (processor)           => DCACHE_XTN_*
2180                      // 5) DTLB miss (processor)             => DCACHE_TLB_MISS
2181                      // 6) Dirty bit update (processor)      => DCACHE_DIRTY_GET_PTE
2182                      // 7) Cacheable read miss (processor)   => DCACHE_MISS_SELECT
2183                      // 8) Uncacheable read (processor)      => DCACHE_UNC_WAIT
2184                      // 9) LL access (processor)             => DCACHE_LL_WAIT
2185                      // 10) SC access (processor)            => DCACHE_SC_WAIT
2186                      //
2187                      // There is a fixed priority to handle requests to DCACHE:
2188                      //    1/ the ITLB/DTLB invalidate requests
2189                      //    2/ the coherence requests,
2190                      //    3/ the processor requests (including DTLB miss),
2191                      //    4/ the ITLB miss requests,
2192                      // The address space processor request are handled as follows:
2193                      // - WRITE request is blocked if the Dirty bit mus be set.
2194                      // If DTLB hit, the P1 stage is activated (writes WBUF, and
2195                      // updates DCACHE if DCACHE hit) & processor request acknowledged.
2196                      // - READ request generate a simultaneouss access to  DCACHE.DATA
2197                      // and DCACHE.DIR, but is delayed if DCACHE update required.
2198                      //
2199                      // There is 4 configurations defining the access type to
2200                      // DTLB, DCACHE.DATA, and DCACHE.DIR, depending on the
2201                      // dreq.valid (dreq) and r_dcache_updt_req (updt) signals:
2202                      //    dreq / updt / DTLB  / DCACHE.DIR / DCACHE.DATA /
2203                      //     0   /  0   / NOP   / NOP        / NOP         /
2204                      //     0   /  1   / NOP   / NOP        / WRITE       /
2205                      //     1   /  0   / READ  / READ       / NOP         /
2206                      //     1   /  1   / READ  / READ       / WRITE       /
2207                      // Those two registers are set at each cycle from the 3 signals
2208                      // updt_request, wbuf_request, wbuf_write_miss.
2209    {
2210        paddr_t     paddr;                          // physical address
2211        pte_info_t      tlb_flags;
2212        size_t          tlb_way;
2213        size_t          tlb_set;
2214        paddr_t         tlb_nline = 0;
2215        size_t          cache_way;
2216        size_t          cache_set;
2217        size_t          cache_word;
2218        uint32_t        cache_rdata = 0;
2219        bool        tlb_hit = false;
2220        int             cache_state = CACHE_SLOT_STATE_EMPTY;
2221
2222        bool        tlb_inval_required = false;     // request TLB inval after cache update
2223        bool        wbuf_write_miss    = false;     // miss a WBUF write request
2224        bool        updt_request       = false;     // request DCACHE update in P1 stage
2225        bool        wbuf_request       = false;     // request WBUF write in P1 stage
2226
2227        // physical address computation : systematic DTLB access if activated)
2228        if ( m_dreq.valid )
2229        {
2230            if ( r_mmu_mode.read() & DATA_TLB_MASK )  // DTLB activated
2231            {
2232                tlb_hit = r_dtlb.translate( m_dreq.addr,
2233                                            &paddr,
2234                                            &tlb_flags,
2235                                            &tlb_nline,
2236                                            &tlb_way,
2237                                            &tlb_set );
2238#ifdef INSTRUMENTATION
2239m_cpt_dtlb_read++;
2240#endif
2241            }
2242            else                                    // identity mapping
2243            {
2244                paddr = (paddr_t)m_dreq.addr;
2245                // we take into account the paddr extension
2246                if (vci_param::N > 32) 
2247                    paddr = paddr | ((paddr_t)(r_dcache_paddr_ext.read()) << 32);
2248            }
2249        } // end physical address computation
2250
2251        // systematic DCACHE access depending on r_dcache_updt_req (if activated)
2252        if ( r_mmu_mode.read() & DATA_CACHE_MASK)
2253        {
2254            if ( m_dreq.valid and r_dcache_updt_req.read() ) // read DIR and write DATA
2255            {
2256                r_dcache.read_dir( paddr,
2257                                   &cache_state,
2258                                   &cache_way,
2259                                   &cache_set,
2260                                   &cache_word );
2261
2262                r_dcache.write( r_dcache_save_cache_way.read(),
2263                                r_dcache_save_cache_set.read(),
2264                                r_dcache_save_cache_word.read(),
2265                                r_dcache_save_wdata.read(),
2266                                r_dcache_save_be.read() );
2267#ifdef INSTRUMENTATION
2268m_cpt_dcache_dir_read++;
2269m_cpt_dcache_data_write++;
2270#endif
2271            }
2272            else if ( m_dreq.valid and not r_dcache_updt_req.read() ) // read DIR and DATA
2273            {
2274                r_dcache.read( paddr,
2275                               &cache_rdata,
2276                               &cache_way,
2277                               &cache_set,
2278                               &cache_word,
2279                               &cache_state );
2280
2281#ifdef INSTRUMENTATION
2282m_cpt_dcache_dir_read++;
2283m_cpt_dcache_data_read++;
2284#endif
2285            }
2286            else if ( not m_dreq.valid and r_dcache_updt_req.read() ) // write DATA
2287            {
2288                r_dcache.write( r_dcache_save_cache_way.read(),
2289                                r_dcache_save_cache_set.read(),
2290                                r_dcache_save_cache_word.read(),
2291                                r_dcache_save_wdata.read(),
2292                                r_dcache_save_be.read() );
2293#ifdef INSTRUMENTATION
2294m_cpt_dcache_data_write++;
2295#endif
2296            }
2297        } // end dcache access
2298
2299        // DCACHE update in P1 stage can require ITLB / DTLB inval or flush
2300        if ( r_dcache_updt_req.read() )
2301        {
2302            size_t way = r_dcache_save_cache_way.read();
2303            size_t set = r_dcache_save_cache_set.read();
2304
2305            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
2306            {
2307                tlb_inval_required       = true;
2308                    r_dcache_tlb_inval_set   = 0;
2309                    r_dcache_tlb_inval_line  = r_dcache_save_paddr.read()>>
2310                                           (uint32_log2(m_dcache_words<<2));
2311                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
2312            }
2313            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
2314            {
2315                r_itlb.reset();
2316                r_dtlb.reset();
2317                    r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
2318            }
2319
2320#if DEBUG_DCACHE
2321if ( m_debug_activated )
2322std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2323          << " Cache update in P1 stage" << std::dec
2324          << " / WAY = " << r_dcache_save_cache_way.read()
2325          << " / SET = " << r_dcache_save_cache_set.read()
2326          << " / WORD = " << r_dcache_save_cache_word.read() << std::hex
2327          << " / WDATA = " << r_dcache_save_wdata.read()
2328          << " / BE = " << r_dcache_save_be.read() << std::endl;
2329#endif
2330        } // end test TLB inval
2331
2332        // Try WBUF update in P1 stage
2333        // Miss if the write request is non cacheable, and there is a pending
2334        // non cacheable write, or if the write buffer is full.
2335        if ( r_dcache_wbuf_req.read() )
2336        {
2337            // miss if write not cacheable, and previous non cacheable write registered
2338            if ( not r_dcache_save_cacheable.read() and r_dcache_pending_unc_write.read() )
2339            {
2340                wbuf_write_miss = true;
2341            }
2342            else                // try a registration into write buffer
2343            {
2344                bool wok = r_wbuf.write( r_dcache_save_paddr.read(),
2345                                         r_dcache_save_be.read(),
2346                                         r_dcache_save_wdata.read(),
2347                                         r_dcache_save_cacheable.read() );
2348#ifdef INSTRUMENTATION
2349m_cpt_wbuf_write++;
2350#endif
2351                if ( not wok ) // miss if write buffer full
2352                {
2353                    wbuf_write_miss = true;
2354                }
2355                else          // update the write_buffer state extension
2356                {
2357                    if(not r_dcache_pending_unc_write.read())
2358                        r_dcache_pending_unc_write = not r_dcache_save_cacheable.read();
2359                }
2360            }
2361        } // end WBUF update
2362
2363        // Computing the response to processor,
2364        // and the next value for r_dcache_fsm
2365
2366        // itlb/dtlb invalidation self-request
2367        if ( tlb_inval_required )
2368        {
2369            r_dcache_fsm_scan_save = r_dcache_fsm.read();
2370            r_dcache_fsm           = DCACHE_INVAL_TLB_SCAN;
2371        }
2372
2373        // coherence clack request (from DSPIN CLACK)
2374        else if ( r_dcache_clack_req.read() )
2375        {
2376            r_dcache_fsm = DCACHE_CC_CHECK;
2377            r_dcache_fsm_cc_save = r_dcache_fsm.read();
2378        }
2379        // coherence request (from CC_RECEIVE FSM)
2380        else if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
2381        {
2382            r_dcache_fsm = DCACHE_CC_CHECK;
2383            r_dcache_fsm_cc_save = r_dcache_fsm.read();
2384        }
2385
2386        // processor request (READ, WRITE, LL, SC, XTN_READ, XTN_WRITE)
2387        // we don't take the processor request, and registers
2388        // are frozen in case of wbuf_write_miss
2389        else if ( m_dreq.valid and not wbuf_write_miss )
2390        {
2391            // register processor request and DCACHE response
2392            r_dcache_save_vaddr      = m_dreq.addr;
2393            r_dcache_save_be         = m_dreq.be;
2394            r_dcache_save_wdata      = m_dreq.wdata;
2395            r_dcache_save_paddr      = paddr;
2396            r_dcache_save_cache_way  = cache_way;
2397            r_dcache_save_cache_set  = cache_set;
2398            r_dcache_save_cache_word = cache_word;
2399
2400            // READ XTN requests from processor
2401            // They are executed in this DCACHE_IDLE state.
2402            // The processor must not be in user mode
2403            if (m_dreq.type == iss_t::XTN_READ)
2404            {
2405                int xtn_opcode = (int)m_dreq.addr/4;
2406
2407                // checking processor mode:
2408                if (m_dreq.mode  == iss_t::MODE_USER)
2409                {
2410                    r_mmu_detr   = MMU_READ_PRIVILEGE_VIOLATION;
2411                    r_mmu_dbvar  = m_dreq.addr;
2412                    m_drsp.valid = true;
2413                    m_drsp.error = true;
2414                    m_drsp.rdata = 0;
2415                    r_dcache_fsm = DCACHE_IDLE;
2416                }
2417                else
2418                {
2419                    switch( xtn_opcode )
2420                    {
2421                    case iss_t::XTN_INS_ERROR_TYPE:
2422                        m_drsp.rdata = r_mmu_ietr.read();
2423                        m_drsp.valid = true;
2424                        m_drsp.error = false;
2425                        break;
2426
2427                    case iss_t::XTN_DATA_ERROR_TYPE:
2428                        m_drsp.rdata = r_mmu_detr.read();
2429                        m_drsp.valid = true;
2430                        m_drsp.error = false;
2431                        break;
2432
2433                    case iss_t::XTN_INS_BAD_VADDR:
2434                        m_drsp.rdata = r_mmu_ibvar.read();
2435                        m_drsp.valid = true;
2436                        m_drsp.error = false;
2437                        break;
2438
2439                    case iss_t::XTN_DATA_BAD_VADDR:
2440                        m_drsp.rdata = r_mmu_dbvar.read();
2441                        m_drsp.valid = true;
2442                        m_drsp.error = false;
2443                        break;
2444
2445                    case iss_t::XTN_PTPR:
2446                        m_drsp.rdata = r_mmu_ptpr.read();
2447                        m_drsp.valid = true;
2448                        m_drsp.error = false;
2449                        break;
2450
2451                    case iss_t::XTN_TLB_MODE:
2452                        m_drsp.rdata = r_mmu_mode.read();
2453                        m_drsp.valid = true;
2454                        m_drsp.error = false;
2455                        break;
2456
2457                    case iss_t::XTN_MMU_PARAMS:
2458                        m_drsp.rdata = r_mmu_params;
2459                        m_drsp.valid = true;
2460                        m_drsp.error = false;
2461                        break;
2462
2463                    case iss_t::XTN_MMU_RELEASE:
2464                        m_drsp.rdata = r_mmu_release;
2465                        m_drsp.valid = true;
2466                        m_drsp.error = false;
2467                        break;
2468
2469                    case iss_t::XTN_MMU_WORD_LO:
2470                        m_drsp.rdata = r_mmu_word_lo.read();
2471                        m_drsp.valid = true;
2472                        m_drsp.error = false;
2473                        break;
2474
2475                    case iss_t::XTN_MMU_WORD_HI:
2476                        m_drsp.rdata = r_mmu_word_hi.read();
2477                        m_drsp.valid = true;
2478                        m_drsp.error = false;
2479                        break;
2480
2481                    case iss_t::XTN_DATA_PADDR_EXT:
2482                        m_drsp.rdata = r_dcache_paddr_ext.read();
2483                        m_drsp.valid = true;
2484                        m_drsp.error = false;
2485                        break;
2486
2487                    default:
2488                        r_mmu_detr = MMU_READ_UNDEFINED_XTN;
2489                        r_mmu_dbvar  = m_dreq.addr;
2490                        m_drsp.valid = true;
2491                        m_drsp.error = true;
2492                        m_drsp.rdata = 0;
2493                        break;
2494                    } // end switch xtn_opcode
2495                } // end else
2496            } // end if XTN_READ
2497
2498            // Handling WRITE XTN requests from processor.
2499            // They are not executed in this DCACHE_IDLE state
2500            // if they require access to the caches or the TLBs
2501            // that are already accessed.
2502            // Caches can be invalidated or flushed in user mode,
2503            // and the sync instruction can be executed in user mode
2504            else if (m_dreq.type == iss_t::XTN_WRITE)
2505            {
2506                int xtn_opcode      = (int)m_dreq.addr/4;
2507                r_dcache_xtn_opcode = xtn_opcode;
2508
2509                // checking processor mode:
2510                if ( (m_dreq.mode  == iss_t::MODE_USER) &&
2511                     (xtn_opcode != iss_t::XTN_SYNC) &&
2512                     (xtn_opcode != iss_t::XTN_DCACHE_INVAL) &&
2513                     (xtn_opcode != iss_t::XTN_DCACHE_FLUSH) &&
2514                     (xtn_opcode != iss_t::XTN_ICACHE_INVAL) &&
2515                     (xtn_opcode != iss_t::XTN_ICACHE_FLUSH) )
2516                {
2517                    r_mmu_detr   = MMU_WRITE_PRIVILEGE_VIOLATION;
2518                    r_mmu_dbvar  = m_dreq.addr;
2519                    m_drsp.valid = true;
2520                    m_drsp.error = true;
2521                    m_drsp.rdata = 0;
2522                    r_dcache_fsm = DCACHE_IDLE;
2523                }
2524                else
2525                {
2526                    switch( xtn_opcode )
2527                    {
2528                    case iss_t::XTN_PTPR:                       // itlb & dtlb must be flushed
2529                        r_dcache_xtn_req = true;
2530                        r_dcache_fsm     = DCACHE_XTN_SWITCH;
2531                        break;
2532
2533                    case iss_t::XTN_TLB_MODE:                   // no cache or tlb access
2534                        r_mmu_mode       = m_dreq.wdata;
2535                        m_drsp.valid     = true;
2536                        r_dcache_fsm     = DCACHE_IDLE;
2537                        break;
2538
2539                    case iss_t::XTN_DTLB_INVAL:                 // dtlb access
2540                        r_dcache_fsm     = DCACHE_XTN_DT_INVAL;
2541                        break;
2542
2543                    case iss_t::XTN_ITLB_INVAL:                 // itlb access
2544                        r_dcache_xtn_req = true;
2545                        r_dcache_fsm     = DCACHE_XTN_IT_INVAL;
2546                        break;
2547
2548                    case iss_t::XTN_DCACHE_INVAL:               // dcache, dtlb & itlb access
2549                        r_dcache_fsm     = DCACHE_XTN_DC_INVAL_VA;
2550                        break;
2551
2552                    case iss_t::XTN_MMU_DCACHE_PA_INV:          // dcache, dtlb & itlb access
2553                        r_dcache_fsm     = DCACHE_XTN_DC_INVAL_PA;
2554                        if (sizeof(paddr_t) <= 32)
2555                        {
2556                            assert(r_mmu_word_hi.read() == 0 &&
2557                            "high bits should be 0 for 32bit paddr");
2558                            r_dcache_save_paddr = (paddr_t)r_mmu_word_lo.read();
2559                        }
2560                        else
2561                        {
2562                            r_dcache_save_paddr = (paddr_t)r_mmu_word_hi.read() << 32 |
2563                                                  (paddr_t)r_mmu_word_lo.read();
2564                        }
2565                        break;
2566
2567                    case iss_t::XTN_DCACHE_FLUSH:              // itlb and dtlb must be reset
2568                        r_dcache_flush_count = 0;
2569                        r_dcache_fsm     = DCACHE_XTN_DC_FLUSH;
2570                        break;
2571
2572                    case iss_t::XTN_ICACHE_INVAL:               // icache and itlb access
2573                        r_dcache_xtn_req = true;
2574                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_VA;
2575                        break;
2576
2577                    case iss_t::XTN_MMU_ICACHE_PA_INV:          // icache access
2578                        r_dcache_xtn_req = true;
2579                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_PA;
2580                        break;
2581
2582                    case iss_t::XTN_ICACHE_FLUSH:               // icache access
2583                        r_dcache_xtn_req = true;
2584                        r_dcache_fsm     = DCACHE_XTN_IC_FLUSH;
2585                        break;
2586
2587                    case iss_t::XTN_SYNC:                       // wait until write buffer empty
2588                        r_dcache_fsm     = DCACHE_XTN_SYNC;
2589                        break;
2590
2591                    case iss_t::XTN_MMU_WORD_LO:                // no cache or tlb access
2592                        r_mmu_word_lo    = m_dreq.wdata;
2593                        m_drsp.valid     = true;
2594                        r_dcache_fsm     = DCACHE_IDLE;
2595                        break;
2596
2597                    case iss_t::XTN_MMU_WORD_HI:                // no cache or tlb access
2598                        r_mmu_word_hi    = m_dreq.wdata;
2599                        m_drsp.valid     = true;
2600                        r_dcache_fsm     = DCACHE_IDLE;
2601                        break;
2602
2603                    case iss_t::XTN_MMU_LL_RESET:      // no cache or tlb access
2604                        r_dcache_llsc_valid = false;
2605                        m_drsp.valid     = true;
2606                        r_dcache_fsm     = DCACHE_IDLE;
2607                    break;
2608
2609                    case iss_t::XTN_DATA_PADDR_EXT:     // no cache or tlb access
2610                        r_dcache_paddr_ext = m_dreq.wdata;
2611                        m_drsp.valid       = true;
2612                        r_dcache_fsm       = DCACHE_IDLE;
2613                    break;
2614
2615                        case iss_t::XTN_ICACHE_PREFETCH:                // not implemented : no action
2616                        case iss_t::XTN_DCACHE_PREFETCH:                // not implemented : no action
2617                        m_drsp.valid     = true;
2618                        r_dcache_fsm     = DCACHE_IDLE;
2619                            break;
2620
2621                    default:
2622                        r_mmu_detr   = MMU_WRITE_UNDEFINED_XTN;
2623                        r_mmu_dbvar  = m_dreq.addr;
2624                        m_drsp.valid = true;
2625                        m_drsp.error = true;
2626                        r_dcache_fsm = DCACHE_IDLE;
2627                        break;
2628                    } // end switch xtn_opcode
2629                } // end else
2630            } // end if XTN_WRITE
2631
2632            // Handling processor requests to address space (READ/WRITE/LL/SC)
2633            // The dtlb and dcache can be activated or not.
2634            // We compute the cacheability, and check processor request validity:
2635            // - If DTLB not activated : cacheability is defined by the segment table,
2636            //   and there is no access rights checking.
2637            // - If DTLB activated : cacheability is defined by the C bit in the PTE,
2638            //   and the U & W bits of the PTE are checked, as well as the DTLB hit.
2639            //   Jumps to the TLB_MISS sub-fsm in case of dtlb miss.
2640            else
2641            {
2642                bool        valid_req;
2643                bool        cacheable;
2644
2645                if ( not (r_mmu_mode.read() & DATA_TLB_MASK) )          // dtlb not activated
2646                {
2647                    valid_req     = true;
2648
2649                    if ( not (r_mmu_mode.read() & DATA_CACHE_MASK) ) cacheable = false;
2650                    else cacheable = m_cacheability_table[m_dreq.addr];
2651                }
2652                else                                                                       // dtlb activated
2653                {
2654                    if ( tlb_hit )                                      // tlb hit
2655                    {
2656                        // cacheability
2657                        if ( not (r_mmu_mode.read() & DATA_CACHE_MASK) ) cacheable = false;
2658                        else cacheable = tlb_flags.c;
2659
2660                        // access rights checking
2661                        if ( not tlb_flags.u and (m_dreq.mode == iss_t::MODE_USER))
2662                        {
2663                            if ( (m_dreq.type == iss_t::DATA_READ) or
2664                                 (m_dreq.type == iss_t::DATA_LL) )
2665                            {
2666                                r_mmu_detr = MMU_READ_PRIVILEGE_VIOLATION;
2667                            }
2668                            else
2669                            {
2670                                r_mmu_detr = MMU_WRITE_PRIVILEGE_VIOLATION;
2671                            }
2672                            valid_req    = false;
2673                            r_mmu_dbvar  = m_dreq.addr;
2674                            m_drsp.valid = true;
2675                            m_drsp.error = true;
2676                            m_drsp.rdata = 0;
2677#if DEBUG_DCACHE
2678if ( m_debug_activated )
2679std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2680          << " HIT in dtlb, but privilege violation" << std::endl;
2681#endif
2682                        }
2683                        else if ( not tlb_flags.w and
2684                                  ((m_dreq.type == iss_t::DATA_WRITE) or
2685                                   (m_dreq.type == iss_t::DATA_SC)) )
2686                        {
2687                            r_mmu_detr   = MMU_WRITE_ACCES_VIOLATION;
2688                            valid_req    = false;
2689                            r_mmu_dbvar  = m_dreq.addr;
2690                            m_drsp.valid = true;
2691                            m_drsp.error = true;
2692                            m_drsp.rdata = 0;
2693#if DEBUG_DCACHE
2694if ( m_debug_activated )
2695std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2696          << " HIT in dtlb, but writable violation" << std::endl;
2697#endif
2698                        }
2699                        else
2700                        {
2701                            valid_req    = true;
2702                        }
2703                    }
2704                    else                                                // tlb miss
2705                    {
2706                        valid_req            = false;
2707                        r_dcache_tlb_vaddr   = m_dreq.addr;
2708                        r_dcache_tlb_ins     = false;
2709                        r_dcache_fsm         = DCACHE_TLB_MISS;
2710                    }
2711                }    // end DTLB activated
2712
2713                if ( valid_req )        // processor request is valid (after MMU check)
2714                {
2715                    r_dcache_save_cacheable  = cacheable;
2716
2717                    // READ request
2718                    // The read requests are taken only if there is no cache update.
2719                    // We request a VCI transaction to CMD FSM if miss or uncachable
2720
2721                    if ( ((m_dreq.type == iss_t::DATA_READ))
2722                          and not r_dcache_updt_req.read() )
2723                    {
2724                        if ( cacheable )                // cacheable read
2725                        {
2726                            if ( cache_state == CACHE_SLOT_STATE_EMPTY )   // cache miss
2727                            {
2728#ifdef INSTRUMENTATION
2729m_cpt_dcache_miss++;
2730#endif
2731                                // request a VCI DMISS transaction
2732                                r_dcache_vci_paddr    = paddr;
2733                                r_dcache_vci_miss_req = true;
2734                                r_dcache_miss_type    = PROC_MISS;
2735                                r_dcache_fsm          = DCACHE_MISS_SELECT;
2736#if DEBUG_DCACHE
2737if ( m_debug_activated )
2738std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2739          << " READ MISS in dcache" 
2740          << " / PADDR = " << std::hex << paddr << std::endl;
2741#endif
2742                            }
2743                            else if (cache_state == CACHE_SLOT_STATE_ZOMBI ) // pending cleanup
2744                            {
2745                                // stalled until cleanup is acknowledged
2746                                r_dcache_fsm   = DCACHE_IDLE;
2747#if DEBUG_DCACHE
2748if ( m_debug_activated )
2749std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2750          << " Pending cleanup, stalled until cleanup acknowledge"
2751          << " / PADDR = " << std::hex << paddr << std::endl;
2752#endif
2753                            }
2754                            else                                      // cache hit
2755                            {
2756#ifdef INSTRUMENTATION
2757m_cpt_data_read++;
2758#endif
2759                                // returns data to processor
2760                                m_drsp.valid   = true;
2761                                m_drsp.error   = false;
2762                                m_drsp.rdata   = cache_rdata;
2763#if DEBUG_DCACHE
2764if ( m_debug_activated )
2765std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2766          << " READ HIT in dcache" 
2767          << " / PADDR = " << std::hex << paddr << std::endl;
2768#endif
2769                            }
2770                        }
2771                        else                                    // uncacheable read
2772                        {
2773                            r_dcache_vci_paddr    = paddr;
2774                            r_dcache_vci_unc_be   = m_dreq.be;
2775                            r_dcache_vci_unc_req  = true;
2776                            r_dcache_fsm          = DCACHE_UNC_WAIT;
2777#if DEBUG_DCACHE
2778if ( m_debug_activated )
2779std::cout << "  <PROC " << name() << " DCACHE_IDLE>"
2780          << " READ UNCACHEABLE in dcache" 
2781          << " / PADDR = " << std::hex << paddr << std::endl;
2782#endif
2783                        }
2784                    } // end READ
2785
2786                    // LL request (non cachable)
2787                    // We request a VCI LL transaction to CMD FSM and register
2788                    // the LL/SC operation in llsc buffer.
2789                    else if (m_dreq.type == iss_t::DATA_LL)
2790                    {
2791                        // register paddr in LLSC buffer
2792                        r_dcache_llsc_paddr = paddr;
2793                        r_dcache_llsc_count = LLSC_TIMEOUT;
2794                        r_dcache_llsc_valid = true;
2795
2796                        // request an LL VCI transaction and go to DCACHE_LL_WAIT state
2797                        r_dcache_vci_ll_req   = true;
2798                        r_dcache_vci_paddr    = paddr;
2799                        r_dcache_ll_rsp_count = 0;
2800                        r_dcache_fsm          = DCACHE_LL_WAIT;
2801
2802                    }// end LL
2803
2804                    // WRITE request:
2805                    // If the TLB is activated and the PTE Dirty bit is not set, we stall
2806                    // the processor and set the Dirty bit before handling the write request,
2807                    // going to the DCACHE_DIRTY_GT_PTE state.
2808                    // If we don't need to set the Dirty bit, we can acknowledge
2809                    // the processor request, as the write arguments (including the
2810                    // physical address) are registered in r_dcache_save registers,
2811                    // and the write will be done in the P1 pipeline stage.
2812                    else if ( m_dreq.type == iss_t::DATA_WRITE )
2813                    {
2814                        if ( (r_mmu_mode.read() & DATA_TLB_MASK )
2815                              and not tlb_flags.d )             // Dirty bit must be set
2816                        {
2817                            // The PTE physical address is obtained from the nline value (dtlb),
2818                            // and from the virtual address (word index)
2819                            if ( tlb_flags.b )  // PTE1
2820                            {
2821                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2822                                                       (paddr_t)((m_dreq.addr>>19) & 0x3c);
2823                            }
2824                            else                // PTE2
2825                            {
2826                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2827                                                       (paddr_t)((m_dreq.addr>>9) & 0x38);
2828                            }
2829                            r_dcache_fsm      = DCACHE_DIRTY_GET_PTE;
2830                        }
2831                        else                                    // Write request accepted
2832                        {
2833#ifdef INSTRUMENTATION
2834m_cpt_data_write++;
2835#endif
2836                            // cleaning llsc buffer if address matching
2837                            if ( paddr == r_dcache_llsc_paddr.read() )
2838                                r_dcache_llsc_valid = false;
2839
2840                            // response to processor
2841                            m_drsp.valid        = true;
2842
2843                            // activating P1 stage
2844                            wbuf_request = true;
2845                            updt_request = (cache_state == CACHE_SLOT_STATE_VALID);
2846                        }
2847                    } // end WRITE
2848
2849                    // SC request:
2850                    // If the TLB is activated and the PTE Dirty bit is not set, we stall
2851                    // the processor and set the Dirty bit before handling the write request,
2852                    // going to the DCACHE_DIRTY_GT_PTE state.
2853                    // If we don't need to set the Dirty bit, we test the llsc buffer:
2854                    // If failure, we send a negative response to processor.
2855                    // If success, we request a SC transaction to CMD FSM and go
2856                    // to DCACHE_SC_WAIT state.
2857                    // We don't check a possible write hit in dcache, as the cache update
2858                    // is done by the coherence transaction induced by the SC...
2859                    else if ( m_dreq.type == iss_t::DATA_SC )
2860                    {
2861                        if ( (r_mmu_mode.read() & DATA_TLB_MASK )
2862                              and not tlb_flags.d )                     // Dirty bit must be set
2863                        {
2864                            // The PTE physical address is obtained from the nline value (dtlb),
2865                            // and the word index (virtual address)
2866                            if ( tlb_flags.b )  // PTE1
2867                            {
2868                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2869                                                       (paddr_t)((m_dreq.addr>>19) & 0x3c);
2870                            }
2871                            else                        // PTE2
2872                            {
2873                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2874                                                       (paddr_t)((m_dreq.addr>>9) & 0x38);
2875                            }
2876                            r_dcache_fsm           = DCACHE_DIRTY_GET_PTE;
2877                            m_drsp.valid = false;
2878                            m_drsp.error = false;
2879                            m_drsp.rdata = 0;
2880                        }
2881                        else                                    // SC request accepted
2882                        {
2883#ifdef INSTRUMENTATION
2884m_cpt_data_sc++;
2885#endif
2886                            // checking local success
2887                            if( r_dcache_llsc_valid.read() and
2888                                (r_dcache_llsc_paddr.read() == paddr) )  // local success
2889                            {
2890                                // request an SC CMD and go to DCACHE_SC_WAIT state
2891                                r_dcache_vci_paddr   = paddr;
2892                                r_dcache_vci_sc_req  = true;
2893                                r_dcache_vci_sc_data = m_dreq.wdata;
2894                                r_dcache_fsm         = DCACHE_SC_WAIT;
2895                            }
2896                            else                                          // local fail
2897                            {
2898                                    m_drsp.valid = true;
2899                                    m_drsp.error = false;
2900                                    m_drsp.rdata = 0x1;
2901                            }
2902                        }
2903                    } // end SC
2904                } // end valid_req
2905            }  // end if read/write/ll/sc request
2906        } // end processor request
2907
2908        // itlb miss request
2909        else if ( r_icache_tlb_miss_req.read() and not wbuf_write_miss )
2910        {
2911            r_dcache_tlb_ins    = true;
2912            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
2913            r_dcache_fsm        = DCACHE_TLB_MISS;
2914        }
2915
2916        // Computing requests for P1 stage : r_dcache_wbuf_req & r_dcache_updt_req
2917        r_dcache_updt_req = updt_request;
2918        r_dcache_wbuf_req = wbuf_request or
2919                            (r_dcache_wbuf_req.read() and wbuf_write_miss);
2920        break;
2921    }
2922    /////////////////////
2923    case DCACHE_TLB_MISS: // This is the entry point for the sub-fsm handling all tlb miss.
2924                          // Input arguments are:
2925                          // - r_dcache_tlb_vaddr
2926                          // - r_dcache_tlb_ins (true when itlb miss)
2927                          // The sub-fsm access the dcache to find the missing TLB entry,
2928                          // and activates the cache miss procedure in case of miss.
2929                          // It bypass the first level page table access if possible.
2930                          // It uses atomic access to update the R/L access bits
2931                          // in the page table if required.
2932                          // It directly updates the itlb or dtlb, and writes into the
2933                          // r_mmu_ins_* or r_mmu_data* error reporting registers.
2934    {
2935        uint32_t        ptba = 0;
2936        bool            bypass;
2937        paddr_t         pte_paddr;
2938
2939        // evaluate bypass in order to skip first level page table access
2940        if ( r_dcache_tlb_ins.read() )                          // itlb miss
2941        {
2942            bypass = r_itlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba);
2943        }
2944        else                                                    // dtlb miss
2945        {
2946            bypass = r_dtlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba);
2947        }
2948
2949        if ( not bypass )     // Try to read PTE1/PTD1 in dcache
2950        {
2951            pte_paddr = (((paddr_t)r_mmu_ptpr.read()) << (INDEX1_NBITS+2)) |
2952                        ((((paddr_t)r_dcache_tlb_vaddr.read()) >> PAGE_M_NBITS) << 2);
2953            r_dcache_tlb_paddr = pte_paddr;
2954            r_dcache_fsm       = DCACHE_TLB_PTE1_GET;
2955        }
2956        else                  // Try to read PTE2 in dcache
2957        {
2958            pte_paddr = (paddr_t)ptba << PAGE_K_NBITS |
2959                        (paddr_t)(r_dcache_tlb_vaddr.read()&PTD_ID2_MASK)>>(PAGE_K_NBITS-3);
2960            r_dcache_tlb_paddr = pte_paddr;
2961            r_dcache_fsm       = DCACHE_TLB_PTE2_GET;
2962        }
2963
2964#if DEBUG_DCACHE
2965if ( m_debug_activated )
2966{
2967    if ( r_dcache_tlb_ins.read() )
2968        std::cout << "  <PROC " << name() << " DCACHE_TLB_MISS> ITLB miss";
2969    else
2970        std::cout << "  <PROC " << name() << " DCACHE_TLB_MISS> DTLB miss";
2971    std::cout << " / VADDR = " << std::hex << r_dcache_tlb_vaddr.read()
2972              << " / ptpr  = " << (((paddr_t)r_mmu_ptpr.read()) << (INDEX1_NBITS+2))
2973              << " / BYPASS = " << bypass
2974              << " / PTE_ADR = " << pte_paddr << std::endl;
2975}
2976#endif
2977
2978        break;
2979    }
2980    /////////////////////////
2981    case DCACHE_TLB_PTE1_GET:   // try to read a PT1 entry in dcache
2982    {
2983        // coherence clack request (from DSPIN CLACK)
2984        if ( r_dcache_clack_req.read() )
2985        {
2986            r_dcache_fsm = DCACHE_CC_CHECK;
2987            r_dcache_fsm_cc_save = r_dcache_fsm.read();
2988            break;
2989        }
2990
2991        // coherence request (from CC_RECEIVE FSM)
2992        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
2993        {
2994            r_dcache_fsm = DCACHE_CC_CHECK;
2995            r_dcache_fsm_cc_save = r_dcache_fsm.read();
2996            break;
2997        }
2998
2999        uint32_t        entry;
3000        size_t          way;
3001        size_t          set;
3002        size_t          word;
3003        int         cache_state;
3004        r_dcache.read( r_dcache_tlb_paddr.read(),
3005                       &entry,
3006                       &way,
3007                       &set,
3008                       &word,
3009                       &cache_state );
3010#ifdef INSTRUMENTATION
3011m_cpt_dcache_data_read++;
3012m_cpt_dcache_dir_read++;
3013#endif
3014        if ( cache_state == CACHE_SLOT_STATE_VALID )   // hit in dcache
3015        {
3016            if ( not (entry & PTE_V_MASK) )     // unmapped
3017            {
3018                if ( r_dcache_tlb_ins.read() )
3019                {
3020                    r_mmu_ietr             = MMU_READ_PT1_UNMAPPED;
3021                    r_mmu_ibvar            = r_dcache_tlb_vaddr.read();
3022                    r_icache_tlb_miss_req  = false;
3023                    r_icache_tlb_rsp_error = true;
3024                }
3025                else
3026                {
3027                    r_mmu_detr             = MMU_READ_PT1_UNMAPPED;
3028                    r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
3029                    m_drsp.valid             = true;
3030                    m_drsp.error             = true;
3031                }
3032                r_dcache_fsm          = DCACHE_IDLE;
3033
3034#if DEBUG_DCACHE
3035if ( m_debug_activated )
3036{
3037    std::cout << "  <PROC " << name() 
3038              << " DCACHE_TLB_PTE1_GET> HIT in dcache, but unmapped"
3039              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
3040              << std::dec << " / way = " << way
3041              << std::dec << " / set = " << set
3042              << std::dec << " / word = " << word
3043              << std::hex << " / PTE1 = " << entry << std::endl;
3044}
3045#endif
3046
3047            }
3048            else if( entry & PTE_T_MASK )       //  PTD : me must access PT2
3049            {
3050                // mark the cache line ac containing a PTD
3051                r_dcache_contains_ptd[m_dcache_sets*way+set] = true;
3052
3053                // register bypass
3054                if ( r_dcache_tlb_ins.read() )          // itlb
3055                {
3056                    r_itlb.set_bypass(r_dcache_tlb_vaddr.read(),
3057                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1),
3058                                      r_dcache_tlb_paddr.read() / (m_icache_words<<2) );
3059                }
3060                else                                    // dtlb
3061                {
3062                    r_dtlb.set_bypass(r_dcache_tlb_vaddr.read(),
3063                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1),
3064                                      r_dcache_tlb_paddr.read() / (m_dcache_words<<2) );
3065                }
3066                r_dcache_tlb_paddr =
3067                    (paddr_t)(entry & ((1<<(m_paddr_nbits-PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
3068                    (paddr_t)(((r_dcache_tlb_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
3069                r_dcache_fsm       = DCACHE_TLB_PTE2_GET;
3070
3071#if DEBUG_DCACHE
3072if ( m_debug_activated )
3073{
3074    std::cout << "  <PROC " << name() 
3075              << " DCACHE_TLB_PTE1_GET> HIT in dcache"
3076              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
3077              << std::dec << " / way = " << way
3078              << std::dec << " / set = " << set
3079              << std::dec << " / word = " << word
3080              << std::hex << " / PTD = " << entry << std::endl;
3081}
3082#endif
3083            }
3084            else                        //  PTE1 :  we must update the TLB
3085            {
3086                r_dcache_in_tlb[m_icache_sets*way+set] = true;
3087                r_dcache_tlb_pte_flags  = entry;
3088                r_dcache_tlb_cache_way  = way;
3089                r_dcache_tlb_cache_set  = set;
3090                r_dcache_tlb_cache_word = word;
3091                r_dcache_fsm            = DCACHE_TLB_PTE1_SELECT;
3092
3093#if DEBUG_DCACHE
3094if ( m_debug_activated )
3095{
3096    std::cout << "  <PROC " << name() 
3097              << " DCACHE_TLB_PTE1_GET> HIT in dcache"
3098              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
3099              << std::dec << " / way = " << way
3100              << std::dec << " / set = " << set
3101              << std::dec << " / word = " << word
3102              << std::hex << " / PTE1 = " << entry << std::endl;
3103}
3104#endif
3105            }
3106        }
3107        else if ( cache_state == CACHE_SLOT_STATE_ZOMBI ) // pending cleanup
3108        {
3109            // stalled until cleanup is acknowledged
3110            r_dcache_fsm   = DCACHE_TLB_PTE1_GET;
3111        }
3112        else            // we must load the missing cache line in dcache
3113        {
3114            r_dcache_vci_miss_req  = true;
3115            r_dcache_vci_paddr     = r_dcache_tlb_paddr.read();
3116            r_dcache_save_paddr    = r_dcache_tlb_paddr.read();
3117            r_dcache_miss_type     = PTE1_MISS;
3118            r_dcache_fsm           = DCACHE_MISS_SELECT;
3119
3120#if DEBUG_DCACHE
3121if ( m_debug_activated )
3122{
3123    std::cout << "  <PROC " << name() 
3124              << " DCACHE_TLB_PTE1_GET> MISS in dcache:"
3125              << " PTE1 address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
3126}
3127#endif
3128        }
3129        break;
3130    }
3131    ////////////////////////////
3132    case DCACHE_TLB_PTE1_SELECT:        // select a slot for PTE1
3133    {
3134        size_t  way;
3135        size_t  set;
3136
3137        if ( r_dcache_tlb_ins.read() )
3138        {
3139            r_itlb.select( r_dcache_tlb_vaddr.read(),
3140                           true,  // PTE1
3141                           &way,
3142                           &set );
3143#ifdef INSTRUMENTATION
3144m_cpt_itlb_read++;
3145#endif
3146        }
3147        else
3148        {
3149            r_dtlb.select( r_dcache_tlb_vaddr.read(),
3150                           true,  // PTE1
3151                           &way,
3152                           &set );
3153#ifdef INSTRUMENTATION
3154m_cpt_dtlb_read++;
3155#endif
3156        }
3157        r_dcache_tlb_way = way;
3158        r_dcache_tlb_set = set;
3159        r_dcache_fsm     = DCACHE_TLB_PTE1_UPDT;
3160
3161#if DEBUG_DCACHE
3162if ( m_debug_activated )
3163{
3164    if ( r_dcache_tlb_ins.read() )
3165        std::cout << "  <PROC " << name() 
3166                  << " DCACHE_TLB_PTE1_SELECT> Select a slot in ITLB:";
3167    else
3168        std::cout << "  <PROC " << name() 
3169                  << ".DCACHE_TLB_PTE1_SELECT> Select a slot in DTLB:";
3170        std::cout << " way = " << std::dec << way
3171                  << " / set = " << set << std::endl;
3172}
3173#endif
3174        break;
3175    }
3176    //////////////////////////
3177    case DCACHE_TLB_PTE1_UPDT:  // write a new PTE1 in tlb after testing the L/R bit
3178                                // - if L/R bit already set, exit the sub-fsm.
3179                                // - if not, we update the page table but we dont write
3180                                //   neither in DCACHE, nor in TLB, as this will be done by
3181                                //   the coherence mechanism.
3182    {
3183        paddr_t   nline    = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);
3184        uint32_t  pte      = r_dcache_tlb_pte_flags.read();
3185        bool      pt_updt  = false;
3186        bool      local    = true;
3187
3188        // We should compute the access locality:
3189        // The PPN MSB bits define the destination cluster index.
3190        // The m_srcid MSB bits define the source cluster index.
3191        // The number of bits to compare depends on the number of clusters,
3192        // and can be obtained in the mapping table.
3193        // As long as this computation is not done, all access are local.
3194
3195        if ( local )                                            // local access
3196        {
3197            if ( not ((pte & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
3198            {
3199                pt_updt                = true;
3200                r_dcache_vci_cas_old    = pte;
3201                r_dcache_vci_cas_new    = pte | PTE_L_MASK;
3202                pte                    = pte | PTE_L_MASK;
3203                r_dcache_tlb_pte_flags = pte;
3204            }
3205        }
3206        else                                                    // remote access
3207        {
3208            if ( not ((pte & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
3209            {
3210                pt_updt                = true;
3211                r_dcache_vci_cas_old    = pte;
3212                r_dcache_vci_cas_new    = pte | PTE_R_MASK;
3213                pte                    = pte | PTE_R_MASK;
3214                r_dcache_tlb_pte_flags = pte;
3215            }
3216        }
3217
3218        if ( not pt_updt )                                      // update TLB and return
3219        {
3220            if ( r_dcache_tlb_ins.read() )
3221            {
3222                r_itlb.write( true,             // 2M page
3223                              pte,
3224                              0,                // argument unused for a PTE1
3225                              r_dcache_tlb_vaddr.read(),
3226                              r_dcache_tlb_way.read(),
3227                              r_dcache_tlb_set.read(),
3228                              nline );
3229#ifdef INSTRUMENTATION
3230m_cpt_itlb_write++;
3231#endif
3232
3233#if DEBUG_DCACHE
3234if ( m_debug_activated )
3235{
3236    std::cout << "  <PROC " << name() 
3237              << " DCACHE_TLB_PTE1_UPDT> write PTE1 in ITLB"
3238              << " / set = " << std::dec << r_dcache_tlb_set.read()
3239              << " / way = " << r_dcache_tlb_way.read() << std::endl;
3240    r_itlb.printTrace();
3241}
3242#endif
3243            }
3244            else
3245            {
3246                r_dtlb.write( true,             // 2M page
3247                              pte,
3248                              0,                // argument unused for a PTE1
3249                              r_dcache_tlb_vaddr.read(),
3250                              r_dcache_tlb_way.read(),
3251                              r_dcache_tlb_set.read(),
3252                              nline );
3253#ifdef INSTRUMENTATION
3254m_cpt_dtlb_write++;
3255#endif
3256
3257#if DEBUG_DCACHE
3258if ( m_debug_activated )
3259{
3260    std::cout << "  <PROC " << name() 
3261              << " DCACHE_TLB_PTE1_UPDT> write PTE1 in DTLB"
3262              << " / set = " << std::dec << r_dcache_tlb_set.read()
3263              << " / way = " << r_dcache_tlb_way.read() << std::endl;
3264    r_dtlb.printTrace();
3265}
3266#endif
3267            }
3268            r_dcache_fsm = DCACHE_TLB_RETURN;
3269        }
3270        else                            // update page table but not TLB
3271        {
3272            r_dcache_fsm = DCACHE_TLB_LR_UPDT;
3273
3274#if DEBUG_DCACHE
3275if ( m_debug_activated )
3276{
3277    std::cout << "  <PROC " << name() 
3278              << " DCACHE_TLB_PTE1_UPDT> L/R bit update required"
3279              << std::endl;
3280}
3281#endif
3282        }
3283        break;
3284    }
3285    /////////////////////////
3286    case DCACHE_TLB_PTE2_GET:   // Try to get a PTE2 (64 bits) in the dcache
3287    {
3288        // coherence clack request (from DSPIN CLACK)
3289        if ( r_dcache_clack_req.read() )
3290        {
3291            r_dcache_fsm = DCACHE_CC_CHECK;
3292            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3293            break;
3294        }
3295
3296        // coherence request (from CC_RECEIVE FSM)
3297        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
3298        {
3299            r_dcache_fsm = DCACHE_CC_CHECK;
3300            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3301            break;
3302        }
3303
3304        uint32_t        pte_flags;
3305        uint32_t        pte_ppn;
3306        size_t          way;
3307        size_t          set;
3308        size_t          word;
3309        int         cache_state;
3310
3311        r_dcache.read( r_dcache_tlb_paddr.read(),
3312                       &pte_flags,
3313                       &pte_ppn,
3314                       &way,
3315                       &set,
3316                       &word,
3317                       &cache_state );
3318#ifdef INSTRUMENTATION
3319m_cpt_dcache_data_read++;
3320m_cpt_dcache_dir_read++;
3321#endif
3322        if ( cache_state == CACHE_SLOT_STATE_VALID )   // hit in dcache
3323        {
3324            if ( not (pte_flags & PTE_V_MASK) ) // unmapped
3325            {
3326                if ( r_dcache_tlb_ins.read() )
3327                {
3328                    r_mmu_ietr             = MMU_READ_PT2_UNMAPPED;
3329                    r_mmu_ibvar            = r_dcache_tlb_vaddr.read();
3330                    r_icache_tlb_miss_req  = false;
3331                    r_icache_tlb_rsp_error = true;
3332                }
3333                else
3334                {
3335                    r_mmu_detr             = MMU_READ_PT2_UNMAPPED;
3336                    r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
3337                    m_drsp.valid           = true;
3338                    m_drsp.error           = true;
3339                }
3340                r_dcache_fsm               = DCACHE_IDLE;
3341
3342#if DEBUG_DCACHE
3343if ( m_debug_activated )
3344{
3345    std::cout << "  <PROC " << name()
3346              << " DCACHE_TLB_PTE2_GET> HIT in dcache, but PTE unmapped"
3347              << " PTE_FLAGS = " << std::hex << pte_flags
3348              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3349}
3350#endif
3351            }
3352            else                                // mapped : we must update the TLB
3353            {
3354                r_dcache_in_tlb[m_dcache_sets*way+set] = true;
3355                r_dcache_tlb_pte_flags  = pte_flags;
3356                r_dcache_tlb_pte_ppn    = pte_ppn;
3357                r_dcache_tlb_cache_way  = way;
3358                r_dcache_tlb_cache_set  = set;
3359                r_dcache_tlb_cache_word = word;
3360                r_dcache_fsm            = DCACHE_TLB_PTE2_SELECT;
3361
3362#if DEBUG_DCACHE
3363if ( m_debug_activated )
3364{
3365    std::cout << "  <PROC " << name() 
3366              << " DCACHE_TLB_PTE2_GET> HIT in dcache:"
3367              << " PTE_FLAGS = " << std::hex << pte_flags
3368              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3369}
3370#endif
3371             }
3372        }
3373        else if ( cache_state == CACHE_SLOT_STATE_ZOMBI ) // pending cleanup
3374        {
3375            // stalled until cleanup is acknowledged
3376            r_dcache_fsm   = DCACHE_TLB_PTE2_GET;
3377
3378#if DEBUG_DCACHE
3379if ( m_debug_activated )
3380{
3381    std::cout << "  <PROC " << name() 
3382              << " DCACHE_TLB_PTE2_GET> ZOMBI in dcache: waiting cleanup ack"
3383              << std::endl;
3384}
3385#endif
3386        }
3387        else            // we must load the missing cache line in dcache
3388        {
3389            r_dcache_fsm          = DCACHE_MISS_SELECT;
3390            r_dcache_vci_miss_req = true;
3391            r_dcache_vci_paddr    = r_dcache_tlb_paddr.read();
3392            r_dcache_save_paddr   = r_dcache_tlb_paddr.read();
3393            r_dcache_miss_type    = PTE2_MISS;
3394
3395#if DEBUG_DCACHE
3396if ( m_debug_activated )
3397{
3398    std::cout << "  <PROC " << name()
3399              << " DCACHE_TLB_PTE2_GET> MISS in dcache:"
3400              << " PTE address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
3401}
3402#endif
3403        }
3404        break;
3405    }
3406    ////////////////////////////
3407    case DCACHE_TLB_PTE2_SELECT:    // select a slot for PTE2
3408    {
3409        size_t way;
3410        size_t set;
3411
3412        if ( r_dcache_tlb_ins.read() )
3413        {
3414            r_itlb.select( r_dcache_tlb_vaddr.read(),
3415                           false,       // PTE2
3416                           &way,
3417                           &set );
3418#ifdef INSTRUMENTATION
3419m_cpt_itlb_read++;
3420#endif
3421        }
3422        else
3423        {
3424            r_dtlb.select( r_dcache_tlb_vaddr.read(),
3425                           false,       // PTE2
3426                           &way,
3427                           &set );
3428#ifdef INSTRUMENTATION
3429m_cpt_dtlb_read++;
3430#endif
3431        }
3432
3433#if DEBUG_DCACHE
3434if ( m_debug_activated )
3435{
3436    if ( r_dcache_tlb_ins.read() )
3437        std::cout << "  <PROC " << name()
3438                  << " DCACHE_TLB_PTE2_SELECT> Select a slot in ITLB:";
3439    else
3440        std::cout << "  <PROC " << name()
3441                  << " DCACHE_TLB_PTE2_SELECT> Select a slot in DTLB:";
3442        std::cout << " way = " << std::dec << way
3443                  << " / set = " << set << std::endl;
3444}
3445#endif
3446        r_dcache_tlb_way = way;
3447        r_dcache_tlb_set = set;
3448        r_dcache_fsm     = DCACHE_TLB_PTE2_UPDT;
3449        break;
3450    }
3451    //////////////////////////
3452    case DCACHE_TLB_PTE2_UPDT:  // write a new PTE2 in tlb after testing the L/R bit
3453                                // - if L/R bit already set, exit the sub-fsm.
3454                                // - if not, we update the page table but we dont write
3455                                //   neither in DCACHE, nor in TLB, as this will be done by
3456                                //   the coherence mechanism.
3457    {
3458        paddr_t         nline     = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);
3459        uint32_t        pte_flags = r_dcache_tlb_pte_flags.read();
3460        uint32_t        pte_ppn   = r_dcache_tlb_pte_ppn.read();
3461        bool            pt_updt   = false;
3462        bool            local     = true;
3463
3464        // We should compute the access locality:
3465        // The PPN MSB bits define the destination cluster index.
3466        // The m_srcid MSB bits define the source cluster index.
3467        // The number of bits to compare depends on the number of clusters,
3468        // and can be obtained in the mapping table.
3469        // As long as this computation is not done, all access are local.
3470
3471        if ( local )                                            // local access
3472        {
3473            if ( not ((pte_flags & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
3474            {
3475                pt_updt                = true;
3476                r_dcache_vci_cas_old   = pte_flags;
3477                r_dcache_vci_cas_new   = pte_flags | PTE_L_MASK;
3478                pte_flags              = pte_flags | PTE_L_MASK;
3479                        r_dcache_tlb_pte_flags = pte_flags;
3480            }
3481        }
3482        else                                                    // remote access
3483        {
3484            if ( not ((pte_flags & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
3485            {
3486                pt_updt                = true;
3487                r_dcache_vci_cas_old   = pte_flags;
3488                r_dcache_vci_cas_new   = pte_flags | PTE_R_MASK;
3489                pte_flags              = pte_flags | PTE_R_MASK;
3490                        r_dcache_tlb_pte_flags = pte_flags;
3491            }
3492        }
3493
3494        if ( not pt_updt )                       // update TLB
3495        {
3496            if ( r_dcache_tlb_ins.read() )
3497            {
3498                r_itlb.write( false,    // 4K page
3499                              pte_flags,
3500                              pte_ppn,
3501                              r_dcache_tlb_vaddr.read(),
3502                              r_dcache_tlb_way.read(),
3503                              r_dcache_tlb_set.read(),
3504                              nline );
3505#ifdef INSTRUMENTATION
3506m_cpt_itlb_write++;
3507#endif
3508
3509#if DEBUG_DCACHE
3510if ( m_debug_activated )
3511{
3512    std::cout << "  <PROC " << name()
3513              << " DCACHE_TLB_PTE2_UPDT> write PTE2 in ITLB"
3514              << " / set = " << std::dec << r_dcache_tlb_set.read()
3515              << " / way = " << r_dcache_tlb_way.read() << std::endl;
3516    r_itlb.printTrace();
3517}
3518#endif
3519            }
3520            else
3521            {
3522                r_dtlb.write( false,    // 4K page
3523                              pte_flags,
3524                              pte_ppn,
3525                              r_dcache_tlb_vaddr.read(),
3526                              r_dcache_tlb_way.read(),
3527                              r_dcache_tlb_set.read(),
3528                              nline );
3529#ifdef INSTRUMENTATION
3530m_cpt_dtlb_write++;
3531#endif
3532
3533#if DEBUG_DCACHE
3534if ( m_debug_activated )
3535{
3536    std::cout << "  <PROC " << name()
3537              << " DCACHE_TLB_PTE2_UPDT> write PTE2 in DTLB"
3538              << " / set = " << std::dec << r_dcache_tlb_set.read()
3539              << " / way = " << r_dcache_tlb_way.read() << std::endl;
3540    r_dtlb.printTrace();
3541}
3542#endif
3543
3544            }
3545            r_dcache_fsm = DCACHE_TLB_RETURN;
3546        }
3547        else                                   // update page table but not TLB
3548        {
3549            r_dcache_fsm = DCACHE_TLB_LR_UPDT;  // dcache and page table update
3550
3551#if DEBUG_DCACHE
3552if ( m_debug_activated )
3553{
3554    std::cout << "  <PROC " << name()
3555              << " DCACHE_TLB_PTE2_UPDT> L/R bit update required" << std::endl;
3556}
3557#endif
3558        }
3559        break;
3560    }
3561    ////////////////////////
3562    case DCACHE_TLB_LR_UPDT:        // request a CAS transaction to update L/R bit
3563    {
3564#if DEBUG_DCACHE
3565if ( m_debug_activated )
3566{
3567    std::cout << "  <PROC " << name()
3568              << " DCACHE_TLB_LR_UPDT> Update dcache: (L/R) bit" << std::endl;
3569}
3570#endif
3571        // r_dcache_vci_cas_old & r_dcache_vci_cas_new registers are already set
3572        r_dcache_vci_paddr = r_dcache_tlb_paddr.read();
3573
3574        // checking llsc reservation buffer
3575        if ( r_dcache_llsc_paddr.read() == r_dcache_tlb_paddr.read() )
3576            r_dcache_llsc_valid = false;
3577
3578        // request a CAS CMD and go to DCACHE_TLB_LR_WAIT state
3579        r_dcache_vci_cas_req = true;
3580        r_dcache_fsm         = DCACHE_TLB_LR_WAIT;
3581        break;
3582    }
3583    ////////////////////////
3584    case DCACHE_TLB_LR_WAIT:            // Waiting the response to SC transaction for DIRTY bit.
3585                                    // We consume the response in rsp FIFO,
3586                                    // and exit the sub-fsm, but we don't
3587                                    // analyse the response, because we don't
3588                                    // care if the L/R bit update is not done.
3589                                    // We must take the coherence requests because
3590                                    // there is a risk of dead-lock
3591
3592    {
3593        // coherence clack request (from DSPIN CLACK)
3594        if ( r_dcache_clack_req.read() )
3595        {
3596            r_dcache_fsm = DCACHE_CC_CHECK;
3597            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3598            break;
3599        }
3600
3601        // coherence request (from CC_RECEIVE FSM)
3602        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
3603        {
3604            r_dcache_fsm = DCACHE_CC_CHECK;
3605            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3606            break;
3607        }
3608
3609        if ( r_vci_rsp_data_error.read() )      // bus error
3610        {
3611            std::cout << "BUS ERROR in DCACHE_TLB_LR_WAIT state" << std::endl;
3612            std::cout << "This should not happen in this state" << std::endl;
3613            exit(0);
3614        }
3615        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
3616        {
3617#if DEBUG_DCACHE
3618if ( m_debug_activated )
3619{
3620    std::cout << "  <PROC " << name()
3621              << " DCACHE_TLB_LR_WAIT> SC response received" << std::endl;
3622}
3623#endif
3624            vci_rsp_fifo_dcache_get = true;
3625            r_dcache_fsm            = DCACHE_TLB_RETURN;
3626        }
3627        break;
3628    }
3629    ///////////////////////
3630    case DCACHE_TLB_RETURN:             // return to caller depending on tlb miss type
3631    {
3632#if DEBUG_DCACHE
3633if ( m_debug_activated )
3634{
3635    std::cout << "  <PROC " << name()
3636              << " DCACHE_TLB_RETURN> TLB MISS completed" << std::endl;
3637}
3638#endif
3639        if ( r_dcache_tlb_ins.read() ) r_icache_tlb_miss_req = false;
3640        r_dcache_fsm = DCACHE_IDLE;
3641        break;
3642    }
3643    ///////////////////////
3644    case DCACHE_XTN_SWITCH:             // The r_ptpr registers must be written,
3645                                // and both itlb and dtlb must be flushed.
3646                                // Caution : the itlb miss requests must be taken
3647                                // to avoid dead-lock in case of simultaneous ITLB miss
3648    {
3649        // itlb miss request
3650        if ( r_icache_tlb_miss_req.read() )
3651        {
3652            r_dcache_tlb_ins    = true;
3653            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
3654            r_dcache_fsm        = DCACHE_TLB_MISS;
3655            break;
3656        }
3657
3658        if ( not r_dcache_xtn_req.read() )
3659        {
3660            r_dtlb.flush();
3661            r_mmu_ptpr   = m_dreq.wdata;
3662            r_dcache_fsm = DCACHE_IDLE;
3663            m_drsp.valid = true;
3664        }
3665        break;
3666    }
3667    /////////////////////
3668    case DCACHE_XTN_SYNC:               // waiting until write buffer empty
3669                                // The coherence request must be taken
3670                                // as there is a risk of dead-lock
3671    {
3672        // coherence clack request (from DSPIN CLACK)
3673        if ( r_dcache_clack_req.read() )
3674        {
3675            r_dcache_fsm = DCACHE_CC_CHECK;
3676            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3677            break;
3678        }
3679
3680        // coherence request (from CC_RECEIVE FSM)
3681        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
3682        {
3683            r_dcache_fsm = DCACHE_CC_CHECK;
3684            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3685            break;
3686        }
3687
3688        if ( r_wbuf.empty() )
3689        {
3690            m_drsp.valid   = true;
3691            r_dcache_fsm = DCACHE_IDLE;
3692        }
3693        break;
3694    }
3695    ////////////////////////
3696    case DCACHE_XTN_IC_FLUSH:           // Waiting completion of an XTN request to the ICACHE FSM
3697    case DCACHE_XTN_IC_INVAL_VA:        // Caution : the itlb miss requests must be taken
3698    case DCACHE_XTN_IC_INVAL_PA:        // because the XTN_ICACHE_INVAL request to icache
3699    case DCACHE_XTN_IT_INVAL:           // can generate an itlb miss,
3700                                    // and because it can exist a simultaneous ITLB miss
3701    {
3702        // coherence clack request (from DSPIN CLACK)
3703        if ( r_dcache_clack_req.read() )
3704        {
3705            r_dcache_fsm = DCACHE_CC_CHECK;
3706            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3707            break;
3708        }
3709
3710        // coherence request (from CC_RECEIVE FSM)
3711        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
3712        {
3713            r_dcache_fsm = DCACHE_CC_CHECK;
3714            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3715            break;
3716        }
3717
3718        // itlb miss request
3719        if ( r_icache_tlb_miss_req.read() )
3720        {
3721            r_dcache_tlb_ins    = true;
3722            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
3723            r_dcache_fsm        = DCACHE_TLB_MISS;
3724            break;
3725        }
3726
3727        // test if XTN request to icache completed
3728        if ( not r_dcache_xtn_req.read() )
3729        {
3730            r_dcache_fsm = DCACHE_IDLE;
3731            m_drsp.valid = true;
3732        }
3733        break;
3734    }
3735    /////////////////////////
3736    case DCACHE_XTN_DC_FLUSH:   // Invalidate sequencially all cache lines, using
3737                                // r_dcache_flush_count as a slot counter,
3738                                // looping in this state until all slots have been visited.
3739                                // It can require two cycles per slot:
3740                                // We test here the slot state, and make the actual inval
3741                                // (if line is valid) in DCACHE_XTN_DC_FLUSH_GO state.
3742                                // A cleanup request is generated for each valid line.
3743                                // returns to IDLE and flush TLBs when last slot
3744    {
3745        // coherence clack request (from DSPIN CLACK)
3746        if ( r_dcache_clack_req.read() )
3747        {
3748            r_dcache_fsm = DCACHE_CC_CHECK;
3749            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3750            break;
3751        }
3752
3753        // coherence request (from CC_RECEIVE FSM)
3754        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
3755        {
3756            r_dcache_fsm = DCACHE_CC_CHECK;
3757            r_dcache_fsm_cc_save = r_dcache_fsm.read();
3758            break;
3759        }
3760
3761        if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
3762        {
3763            int       state;
3764            paddr_t   tag;
3765            size_t    way = r_dcache_flush_count.read()/m_dcache_sets;
3766            size_t    set = r_dcache_flush_count.read()%m_dcache_sets;
3767
3768#ifdef INSTRUMENTATION
3769m_cpt_dcache_dir_read++;
3770#endif
3771            r_dcache.read_dir( way,
3772                               set,
3773                               &tag,
3774                               &state );
3775
3776            if ( state == CACHE_SLOT_STATE_VALID )         // inval required
3777            {
3778                // request cleanup
3779                r_dcache_cc_send_req   = true;
3780                r_dcache_cc_send_nline = tag * m_dcache_sets + set;
3781                r_dcache_cc_send_way   = way;
3782                r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
3783
3784                // goes to DCACHE_XTN_DC_FLUSH_GO to inval directory
3785                r_dcache_miss_way     = way;
3786                r_dcache_miss_set     = set;
3787                r_dcache_fsm          = DCACHE_XTN_DC_FLUSH_GO;
3788            }
3789            else if ( r_dcache_flush_count.read() ==
3790                      (m_dcache_sets*m_dcache_ways - 1) )  // last slot
3791            {
3792                r_dtlb.reset();
3793                r_itlb.reset();
3794                r_dcache_fsm = DCACHE_IDLE;
3795                m_drsp.valid = true;
3796            }
3797
3798            // saturation counter
3799            if ( r_dcache_flush_count.read() < (m_dcache_sets*m_dcache_ways - 1) )
3800                r_dcache_flush_count = r_dcache_flush_count.read() + 1;
3801        }
3802        break;
3803    }
3804    ////////////////////////////
3805    case DCACHE_XTN_DC_FLUSH_GO:    // Switch the cache slot to ZOMBI state
3806                                    // and reset directory extension.
3807                                    // returns to IDLE and flush TLBs when last slot
3808    {
3809        size_t way = r_dcache_miss_way.read();
3810        size_t set = r_dcache_miss_set.read();
3811
3812        r_dcache_in_tlb[m_dcache_sets*way+set]       = false;
3813        r_dcache_contains_ptd[m_dcache_sets*way+set] = false;
3814
3815#ifdef INSTRUMENTATION
3816m_cpt_dcache_dir_write++;
3817#endif
3818        r_dcache.write_dir( way,
3819                            set,
3820                            CACHE_SLOT_STATE_ZOMBI );
3821
3822        if ( r_dcache_flush_count.read() ==
3823             (m_dcache_sets*m_dcache_ways - 1) )  // last slot
3824        {
3825            r_dtlb.reset();
3826            r_itlb.reset();
3827            r_dcache_fsm = DCACHE_IDLE;
3828            m_drsp.valid = true;
3829        }
3830        else
3831        {
3832            r_dcache_fsm = DCACHE_XTN_DC_FLUSH;
3833        }
3834        break;
3835    }
3836    /////////////////////////
3837    case DCACHE_XTN_DT_INVAL:   // handling processor XTN_DTLB_INVAL request
3838    {
3839        r_dtlb.inval(r_dcache_save_wdata.read());
3840        r_dcache_fsm        = DCACHE_IDLE;
3841        m_drsp.valid          = true;
3842        break;
3843    }
3844    ////////////////////////////
3845    case DCACHE_XTN_DC_INVAL_VA:  // selective cache line invalidate with virtual address
3846                                  // requires 3 cycles: access tlb, read cache, inval cache
3847                                  // we compute the physical address in this state
3848    {
3849        paddr_t paddr;
3850        bool    hit;
3851
3852        if ( r_mmu_mode.read() & DATA_TLB_MASK )        // dtlb activated
3853        {
3854
3855#ifdef INSTRUMENTATION
3856m_cpt_dtlb_read++;
3857#endif
3858            hit = r_dtlb.translate( r_dcache_save_wdata.read(),
3859                                    &paddr );
3860        }
3861        else                                            // dtlb not activated
3862        {
3863            paddr = (paddr_t)r_dcache_save_wdata.read();
3864            if (vci_param::N > 32) 
3865                paddr = paddr | ((paddr_t)(r_dcache_paddr_ext.read()) << 32);
3866            hit   = true;
3867        }
3868
3869        if ( hit )              // tlb hit
3870        {
3871            r_dcache_save_paddr = paddr;
3872            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_PA;
3873        }
3874        else                    // tlb miss
3875        {
3876
3877#ifdef INSTRUMENTATION
3878m_cpt_dtlb_miss++;
3879#endif
3880            r_dcache_tlb_ins    = false;                // dtlb
3881            r_dcache_tlb_vaddr  = r_dcache_save_wdata.read();
3882            r_dcache_fsm        = DCACHE_TLB_MISS;
3883        }
3884
3885#if DEBUG_DCACHE
3886if ( m_debug_activated )
3887{
3888    std::cout << "  <PROC " << name()
3889              << " DCACHE_XTN_DC_INVAL_VA> Compute physical address" << std::hex
3890              << " / VADDR = " << r_dcache_save_wdata.read()
3891              << " / PADDR = " << paddr << std::endl;
3892}
3893#endif
3894
3895        break;
3896    }
3897    ////////////////////////////
3898    case DCACHE_XTN_DC_INVAL_PA:  // selective cache line invalidate with physical address
3899                                  // requires 2 cycles: read cache / inval cache
3900                                  // In this state we read dcache.
3901    {
3902        size_t          way;
3903        size_t          set;
3904        size_t          word;
3905        int         state;
3906
3907#ifdef INSTRUMENTATION
3908m_cpt_dcache_dir_read++;
3909#endif
3910        r_dcache.read_dir( r_dcache_save_paddr.read(),
3911                           &state,
3912                           &way,
3913                           &set,
3914                           &word );
3915
3916        if ( state == CACHE_SLOT_STATE_VALID )  // inval to be done
3917        {
3918            r_dcache_xtn_way = way;
3919            r_dcache_xtn_set = set;
3920            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_GO;
3921        }
3922        else            // miss : nothing to do
3923        {
3924            r_dcache_fsm      = DCACHE_IDLE;
3925            m_drsp.valid      = true;
3926        }
3927
3928#if DEBUG_DCACHE
3929if ( m_debug_activated )
3930{
3931    std::cout << "  <PROC " << name()
3932              << " DCACHE_XTN_DC_INVAL_PA> Test hit in dcache" << std::hex
3933              << " / PADDR = " << r_dcache_save_paddr.read() << std::dec
3934              << " / HIT = " << (state == CACHE_SLOT_STATE_VALID)
3935              << " / SET = " << set
3936              << " / WAY = " << way << std::endl;
3937}
3938#endif
3939        break;
3940    }
3941    ////////////////////////////
3942    case DCACHE_XTN_DC_INVAL_GO:  // In this state, we invalidate the cache line
3943                                              // Blocked if previous cleanup not completed
3944                                  // Test if itlb or dtlb inval is required
3945    {
3946        if ( not r_dcache_cc_send_req.read() ) // blocked until previous cc_send request is sent
3947        {
3948            size_t      way        = r_dcache_xtn_way.read();
3949            size_t      set        = r_dcache_xtn_set.read();
3950            paddr_t nline      = r_dcache_save_paddr.read() / (m_dcache_words<<2);
3951
3952#ifdef INSTRUMENTATION
3953m_cpt_dcache_dir_write++;
3954#endif
3955            r_dcache.write_dir( way,
3956                                set,
3957                                CACHE_SLOT_STATE_ZOMBI );
3958
3959            // request cleanup
3960            r_dcache_cc_send_req   = true;
3961            r_dcache_cc_send_nline = nline;
3962            r_dcache_cc_send_way   = way;
3963            r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
3964
3965            // possible itlb & dtlb invalidate
3966            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
3967            {
3968                r_dcache_tlb_inval_line = nline;
3969                r_dcache_tlb_inval_set  = 0;
3970                r_dcache_fsm_scan_save  = DCACHE_XTN_DC_INVAL_END;
3971                r_dcache_fsm            = DCACHE_INVAL_TLB_SCAN;
3972                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3973            }
3974            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
3975            {
3976                r_itlb.reset();
3977                r_dtlb.reset();
3978                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
3979                r_dcache_fsm = DCACHE_IDLE;
3980                m_drsp.valid = true;
3981            }
3982            else
3983            {
3984                r_dcache_fsm = DCACHE_IDLE;
3985                m_drsp.valid = true;
3986            }
3987
3988#if DEBUG_DCACHE
3989if ( m_debug_activated )
3990{
3991    std::cout << "  <PROC " << name()
3992              << " DCACHE_XTN_DC_INVAL_GO> Actual dcache inval" << std::hex
3993              << " / PADDR = " << r_dcache_save_paddr.read() << std::endl;
3994}
3995#endif
3996            }
3997        break;
3998    }
3999    //////////////////////////////
4000    case DCACHE_XTN_DC_INVAL_END:       // send response to processor XTN request
4001    {
4002        r_dcache_fsm = DCACHE_IDLE;
4003        m_drsp.valid = true;
4004        break;
4005    }
4006    ////////////////////////
4007    case DCACHE_MISS_SELECT:       // Try to select a slot in associative set,
4008                                   // Waiting in this state if no slot available.
4009                                   // If a victim slot has been choosen and the r_icache_cc_send_req is false,
4010                                   // we send the cleanup request in this state.
4011                                   // If not, a r_icache_cleanup_victim_req flip-flop is
4012                                   // utilized for saving this cleanup request, and it will be sent later
4013                                   // in state ICACHE_MISS_WAIT or ICACHE_MISS_UPDT_DIR.
4014                                   // The r_icache_miss_clack flip-flop is set
4015                                   // when a cleanup is required
4016    {
4017        if ( m_dreq.valid) m_cost_data_miss_frz++;
4018
4019        // coherence clack request (from DSPIN CLACK)
4020        if ( r_dcache_clack_req.read() )
4021        {
4022            r_dcache_fsm = DCACHE_CC_CHECK;
4023            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4024            break;
4025        }
4026
4027        // coherence request (from CC_RECEIVE FSM)
4028        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
4029        {
4030            r_dcache_fsm = DCACHE_CC_CHECK;
4031            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4032            break;
4033        }
4034
4035        bool     found = false;
4036        bool     cleanup = false;
4037        size_t   way = 0;
4038        size_t   set = 0;
4039        paddr_t  victim = 0;
4040
4041#ifdef INSTRUMENTATION
4042m_cpt_dcache_dir_read++;
4043#endif
4044        r_dcache.read_select( r_dcache_save_paddr.read(),
4045                              &victim,
4046                              &way,
4047                              &set,
4048                              &found,
4049                              &cleanup );
4050
4051        if (  not found )
4052        {
4053            break;
4054        }
4055        else
4056        {
4057            r_dcache_miss_way = way;
4058            r_dcache_miss_set = set;
4059
4060            if ( cleanup )
4061            {
4062                if ( not r_dcache_cc_send_req.read() )
4063                {
4064                    r_dcache_cc_send_req    = true;
4065                    r_dcache_cc_send_nline  = victim;
4066                    r_dcache_cc_send_way    = way;
4067                    r_dcache_cc_send_type   = CC_TYPE_CLEANUP;   
4068
4069                }
4070                else
4071                {
4072                    r_dcache_cleanup_victim_req   = true;
4073                    r_dcache_cleanup_victim_nline = victim;
4074                }
4075
4076                r_dcache_miss_clack           = true;
4077                r_dcache_fsm                  = DCACHE_MISS_CLEAN;
4078            }
4079            else
4080            {
4081                r_dcache_fsm          = DCACHE_MISS_WAIT;
4082            }
4083
4084#if DEBUG_DCACHE
4085if ( m_debug_activated )
4086{
4087    std::cout << "  <PROC " << name()
4088              << " DCACHE_MISS_SELECT> Select a slot:" << std::dec
4089              << " / WAY = "   << way
4090              << " / SET = "   << set
4091              << " / PADDR = " << std::hex << r_dcache_save_paddr.read();
4092    if(cleanup) std::cout << " / VICTIM = " << (victim*m_dcache_words*4) << std::endl;
4093    else        std::cout << std::endl;
4094}
4095#endif
4096        } // end found
4097        break;
4098    }
4099    ///////////////////////
4100    case DCACHE_MISS_CLEAN:             // switch the slot to ZOMBI state
4101                                // and possibly request itlb or dtlb invalidate
4102    {
4103        if ( m_dreq.valid) m_cost_data_miss_frz++;
4104
4105        size_t  way   = r_dcache_miss_way.read();
4106        size_t  set   = r_dcache_miss_set.read();
4107
4108#ifdef INSTRUMENTATION
4109m_cpt_dcache_dir_read++;
4110#endif
4111        r_dcache.write_dir( way,
4112                            set,
4113                            CACHE_SLOT_STATE_ZOMBI );
4114#if DEBUG_DCACHE
4115if ( m_debug_activated )
4116{
4117    std::cout << "  <PROC " << name()
4118              << " DCACHE_MISS_CLEAN> Switch to ZOMBI state" << std::dec
4119              << " / way = "   << way
4120              << " / set = "   << set << std::endl;
4121}
4122#endif
4123        // if selective itlb & dtlb invalidate are required
4124        // the miss response is not handled before invalidate completed
4125        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
4126        {
4127            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4128            r_dcache_tlb_inval_line  = r_dcache_cc_send_nline;
4129            r_dcache_tlb_inval_set   = 0;
4130            r_dcache_fsm_scan_save   = DCACHE_MISS_WAIT;
4131            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4132        }
4133        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
4134        {
4135            r_itlb.reset();
4136            r_dtlb.reset();
4137            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4138            r_dcache_fsm = DCACHE_MISS_WAIT;
4139        }
4140        else
4141        {
4142            r_dcache_fsm = DCACHE_MISS_WAIT;
4143        }
4144        break;
4145    }
4146    //////////////////////
4147    case DCACHE_MISS_WAIT:      // waiting the response to a miss request from VCI_RSP FSM
4148                            // This state is in charge of error signaling
4149                            // There is 5 types of error depending on the requester
4150    {
4151        if ( m_dreq.valid) m_cost_data_miss_frz++;
4152
4153        // coherence clack request (from DSPIN CLACK)
4154        if ( r_dcache_clack_req.read() )
4155        {
4156            r_dcache_fsm = DCACHE_CC_CHECK;
4157            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4158            break;
4159        }
4160
4161        // send cleanup victim request
4162        if ( r_dcache_cleanup_victim_req.read() and not r_dcache_cc_send_req.read() )
4163        {
4164            r_dcache_cc_send_req        = true;
4165            r_dcache_cc_send_nline      = r_dcache_cleanup_victim_nline;
4166            r_dcache_cc_send_way        = r_dcache_miss_way;
4167            r_dcache_cc_send_type       = CC_TYPE_CLEANUP; 
4168            r_dcache_cleanup_victim_req = false;
4169        }   
4170
4171        // coherence request (from CC_RECEIVE FSM)
4172        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read() and not r_dcache_cleanup_victim_req.read())
4173        {
4174            r_dcache_fsm = DCACHE_CC_CHECK;
4175            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4176            break;
4177        }
4178
4179        if ( r_vci_rsp_data_error.read() )                      // bus error
4180        {
4181            switch ( r_dcache_miss_type.read() )
4182            {
4183                case PROC_MISS:
4184                {
4185                    r_mmu_detr            = MMU_READ_DATA_ILLEGAL_ACCESS;
4186                    r_mmu_dbvar           = r_dcache_save_vaddr.read();
4187                    m_drsp.valid            = true;
4188                    m_drsp.error            = true;
4189                    r_dcache_fsm          = DCACHE_IDLE;
4190                    break;
4191                }
4192                case PTE1_MISS:
4193                {
4194                    if ( r_dcache_tlb_ins.read() )
4195                    {
4196                        r_mmu_ietr              = MMU_READ_PT1_ILLEGAL_ACCESS;
4197                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
4198                        r_icache_tlb_miss_req   = false;
4199                        r_icache_tlb_rsp_error  = true;
4200                    }
4201                    else
4202                    {
4203                        r_mmu_detr              = MMU_READ_PT1_ILLEGAL_ACCESS;
4204                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
4205                        m_drsp.valid              = true;
4206                        m_drsp.error              = true;
4207                    }
4208                    r_dcache_fsm                = DCACHE_IDLE;
4209                    break;
4210                }
4211                case PTE2_MISS:
4212                {
4213                    if ( r_dcache_tlb_ins.read() )
4214                    {
4215                        r_mmu_ietr              = MMU_READ_PT2_ILLEGAL_ACCESS;
4216                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
4217                        r_icache_tlb_miss_req   = false;
4218                        r_icache_tlb_rsp_error  = true;
4219                    }
4220                    else
4221                    {
4222                        r_mmu_detr              = MMU_READ_PT2_ILLEGAL_ACCESS;
4223                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
4224                        m_drsp.valid              = true;
4225                        m_drsp.error              = true;
4226                    }
4227                    r_dcache_fsm                = DCACHE_IDLE;
4228                    break;
4229                }
4230            } // end switch type
4231            r_vci_rsp_data_error = false;
4232        }
4233        else if ( r_vci_rsp_fifo_dcache.rok() )         // valid response available
4234        {
4235            r_dcache_miss_word = 0;
4236                r_dcache_fsm       = DCACHE_MISS_DATA_UPDT;
4237        }
4238        break;
4239    }
4240    //////////////////////////
4241    case DCACHE_MISS_DATA_UPDT:   // update the dcache (one word per cycle)
4242    {
4243        if ( m_dreq.valid) m_cost_data_miss_frz++;
4244
4245        if ( r_vci_rsp_fifo_dcache.rok() )      // one word available
4246        {
4247#ifdef INSTRUMENTATION
4248m_cpt_dcache_data_write++;
4249#endif
4250                r_dcache.write( r_dcache_miss_way.read(),
4251                                r_dcache_miss_set.read(),
4252                                r_dcache_miss_word.read(),
4253                                r_vci_rsp_fifo_dcache.read() );
4254#if DEBUG_DCACHE
4255if ( m_debug_activated )
4256{
4257    std::cout << "  <PROC " << name()
4258              << " DCACHE_MISS_DATA_UPDT> Write one word:"
4259              << " / DATA = "  << std::hex << r_vci_rsp_fifo_dcache.read()
4260              << " / WAY = "   << std::dec << r_dcache_miss_way.read()
4261              << " / SET = "   << r_dcache_miss_set.read()
4262              << " / WORD = "  << r_dcache_miss_word.read() << std::endl;
4263}
4264#endif
4265            vci_rsp_fifo_dcache_get = true;
4266            r_dcache_miss_word = r_dcache_miss_word.read() + 1;
4267
4268            if ( r_dcache_miss_word.read() == (m_dcache_words-1) ) // last word
4269            {
4270                r_dcache_fsm = DCACHE_MISS_DIR_UPDT;
4271            }
4272        }
4273        break;
4274    }
4275    //////////////////////////
4276    case DCACHE_MISS_DIR_UPDT:  // Stalled if a victim line has been evicted
4277                                // and the cleanup ack has not been received,
4278                                // as indicated by the r_dcache_miss clack.
4279                                // - If no matching coherence request (r_dcache_inval_miss)
4280                                //   switch directory slot to VALID state.
4281                                // - If matching coherence request, switch directory slot
4282                                //   to ZOMBI state, and send a cleanup request.
4283    {
4284        if ( m_dreq.valid) m_cost_data_miss_frz++;
4285
4286        // coherence clack request (from DSPIN CLACK)
4287        if ( r_dcache_clack_req.read() )
4288        {
4289            r_dcache_fsm = DCACHE_CC_CHECK;
4290            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4291            break;
4292        }
4293
4294        // send cleanup victim request
4295        if ( r_dcache_cleanup_victim_req.read() and not r_dcache_cc_send_req.read() )
4296        {
4297            r_dcache_cc_send_req        = true;
4298            r_dcache_cc_send_nline      = r_dcache_cleanup_victim_nline;
4299            r_dcache_cc_send_way        = r_dcache_miss_way;
4300            r_dcache_cc_send_type       = CC_TYPE_CLEANUP; 
4301            r_dcache_cleanup_victim_req = false;
4302        }   
4303
4304        // coherence request (from CC_RECEIVE FSM)
4305        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read() and not r_dcache_cleanup_victim_req.read() )
4306        {
4307            r_dcache_fsm = DCACHE_CC_CHECK;
4308            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4309            break;
4310        }
4311
4312        if ( not r_dcache_miss_clack.read() )  // waiting cleanup acknowledge
4313        {
4314            if ( r_dcache_miss_inval.read() ) // switch slot to ZOMBI state, and new cleanup
4315            {
4316                if ( not r_dcache_cc_send_req.read() ) // blocked until previous request sent
4317                {
4318                    r_dcache_miss_inval     = false;
4319                    // request cleanup
4320                    r_dcache_cc_send_req   = true;
4321                    r_dcache_cc_send_nline = r_dcache_save_paddr.read()/(m_dcache_words<<2);
4322                    r_dcache_cc_send_way   = r_dcache_miss_way.read();
4323                    r_dcache_cc_send_type  = CC_TYPE_CLEANUP;
4324
4325#ifdef INSTRUMENTATION
4326m_cpt_dcache_dir_write++;
4327#endif
4328                    r_dcache.write_dir( r_dcache_save_paddr.read(),
4329                                        r_dcache_miss_way.read(),
4330                                        r_dcache_miss_set.read(),
4331                                        CACHE_SLOT_STATE_ZOMBI );
4332#if DEBUG_DCACHE
4333if ( m_debug_activated )
4334std::cout << "  <PROC " << name()
4335          << " DCACHE_MISS_DIR_UPDT> Switch slot to ZOMBI state"
4336          << " PADDR = " << std::hex << r_dcache_save_paddr.read()
4337          << " / WAY = "   << std::dec << r_dcache_miss_way.read()
4338          << " / SET = "   << r_dcache_miss_set.read() << std::endl;
4339#endif
4340                }
4341                else
4342                    break;
4343            }
4344            else                              // switch slot to VALID state
4345            {
4346
4347#ifdef INSTRUMENTATION
4348m_cpt_dcache_dir_write++;
4349#endif
4350                r_dcache.write_dir( r_dcache_save_paddr.read(),
4351                                    r_dcache_miss_way.read(),
4352                                    r_dcache_miss_set.read(),
4353                                    CACHE_SLOT_STATE_VALID );
4354
4355#if DEBUG_DCACHE
4356if ( m_debug_activated )
4357std::cout << "  <PROC " << name()
4358          << " DCACHE_MISS_DIR_UPDT> Switch slot to VALID state"
4359          << " PADDR = " << std::hex << r_dcache_save_paddr.read()
4360          << " / WAY = "   << std::dec << r_dcache_miss_way.read()
4361          << " / SET = "   << r_dcache_miss_set.read() << std::endl;
4362#endif
4363                // reset directory extension
4364                size_t way = r_dcache_miss_way.read();
4365                size_t set = r_dcache_miss_set.read();
4366                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4367                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4368            }
4369            if      (r_dcache_miss_type.read()==PTE1_MISS) r_dcache_fsm = DCACHE_TLB_PTE1_GET;
4370            else if (r_dcache_miss_type.read()==PTE2_MISS) r_dcache_fsm = DCACHE_TLB_PTE2_GET;
4371            else                                           r_dcache_fsm = DCACHE_IDLE;
4372        }
4373        break;
4374    }
4375    /////////////////////
4376    case DCACHE_UNC_WAIT:  // waiting a response to an uncacheable read
4377    {
4378        // coherence clack request (from DSPIN CLACK)
4379        if ( r_dcache_clack_req.read() )
4380        {
4381            r_dcache_fsm = DCACHE_CC_CHECK;
4382            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4383            break;
4384        }
4385
4386        // coherence request (from CC_RECEIVE FSM)
4387        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
4388        {
4389            r_dcache_fsm = DCACHE_CC_CHECK;
4390            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4391            break;
4392        }
4393
4394        if ( r_vci_rsp_data_error.read() )      // bus error
4395        {
4396            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS;
4397            r_mmu_dbvar          = m_dreq.addr;
4398            r_vci_rsp_data_error = false;
4399            m_drsp.error         = true;
4400            m_drsp.valid         = true;
4401            r_dcache_fsm         = DCACHE_IDLE;
4402            break;
4403        }
4404            else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
4405            {
4406            // consume data
4407            vci_rsp_fifo_dcache_get = true;
4408            r_dcache_fsm            = DCACHE_IDLE;
4409
4410            // acknowledge the processor request if it has not been modified
4411            if ( m_dreq.valid and (m_dreq.addr == r_dcache_save_vaddr.read()) )
4412            {
4413                    m_drsp.valid        = true;
4414                m_drsp.error        = false;
4415                    m_drsp.rdata        = r_vci_rsp_fifo_dcache.read();
4416            }
4417            }
4418        break;
4419    }
4420    /////////////////////
4421    case DCACHE_LL_WAIT:    // waiting VCI response to a LL transaction
4422    {
4423        // coherence clack request (from DSPIN CLACK)
4424        if ( r_dcache_clack_req.read() )
4425        {
4426            r_dcache_fsm = DCACHE_CC_CHECK;
4427            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4428            break;
4429        }
4430
4431        // coherence request (from CC_RECEIVE FSM)
4432        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
4433        {
4434            r_dcache_fsm = DCACHE_CC_CHECK;
4435            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4436            break;
4437        }
4438
4439        if ( r_vci_rsp_data_error.read() )      // bus error
4440        {
4441            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS;
4442            r_mmu_dbvar          = m_dreq.addr;
4443            r_vci_rsp_data_error = false;
4444            m_drsp.error         = true;
4445            m_drsp.valid         = true;
4446            r_dcache_fsm         = DCACHE_IDLE;
4447            break;
4448        }
4449            else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
4450            {
4451            // consume data
4452            vci_rsp_fifo_dcache_get = true;
4453
4454            if(r_dcache_ll_rsp_count.read() == 0) // first flit
4455            {
4456                // set key value in llsc reservation buffer
4457                r_dcache_llsc_key     = r_vci_rsp_fifo_dcache.read();
4458                r_dcache_ll_rsp_count = r_dcache_ll_rsp_count.read() + 1 ;
4459            }
4460            else                                  // last flit
4461            {
4462                // acknowledge the processor request if it has not been modified
4463                if ( m_dreq.valid and (m_dreq.addr == r_dcache_save_vaddr.read()) )
4464                {
4465                    m_drsp.valid        = true;
4466                    m_drsp.error        = false;
4467                    m_drsp.rdata        = r_vci_rsp_fifo_dcache.read();
4468                }
4469                r_dcache_fsm = DCACHE_IDLE;
4470            }
4471            }
4472        break;
4473    }
4474    ////////////////////
4475    case DCACHE_SC_WAIT:        // waiting VCI response to a SC transaction
4476    {
4477        // coherence clack request (from DSPIN CLACK)
4478        if ( r_dcache_clack_req.read() )
4479        {
4480            r_dcache_fsm = DCACHE_CC_CHECK;
4481            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4482            break;
4483        }
4484
4485        // coherence request (from CC_RECEIVE FSM)
4486        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
4487        {
4488            r_dcache_fsm = DCACHE_CC_CHECK;
4489            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4490            break;
4491        }
4492
4493        if ( r_vci_rsp_data_error.read() )              // bus error
4494        {
4495            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS;
4496            r_mmu_dbvar          = m_dreq.addr;
4497            r_vci_rsp_data_error = false;
4498            m_drsp.error         = true;
4499            m_drsp.valid         = true;
4500            r_dcache_fsm         = DCACHE_IDLE;
4501            break;
4502        }
4503            else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
4504            {
4505            // consume response
4506            vci_rsp_fifo_dcache_get = true;
4507            m_drsp.valid            = true;
4508            m_drsp.rdata            = r_vci_rsp_fifo_dcache.read();
4509            r_dcache_fsm            = DCACHE_IDLE;
4510            }
4511        break;
4512    }
4513    //////////////////////////
4514    case DCACHE_DIRTY_GET_PTE:          // This sub_fsm set the PTE Dirty bit in memory
4515                                    // before handling a processor WRITE or SC request
4516                                    // Input argument is r_dcache_dirty_paddr
4517                                    // In this first state, we get PTE value in dcache
4518                                    // and post a CAS request to CMD FSM
4519    {
4520        // get PTE in dcache
4521        uint32_t pte;
4522        size_t   way;
4523        size_t   set;
4524        size_t   word; // unused
4525        int      state;
4526
4527#ifdef INSTRUMENTATION
4528m_cpt_dcache_data_read++;
4529m_cpt_dcache_dir_read++;
4530#endif
4531        r_dcache.read( r_dcache_dirty_paddr.read(),
4532                       &pte,
4533                       &way,
4534                       &set,
4535                       &word,
4536                       &state );
4537
4538        assert( (state == CACHE_SLOT_STATE_VALID) and
4539        "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
4540
4541        // request CAS transaction to CMD_FSM
4542        r_dcache_dirty_way  = way;
4543        r_dcache_dirty_set  = set;
4544
4545        // check llsc reservation buffer
4546        if (r_dcache_llsc_paddr.read() == r_dcache_dirty_paddr.read() )
4547            r_dcache_llsc_valid = false;
4548
4549        // request a CAS CMD and go to DCACHE_DIRTY_WAIT state
4550        r_dcache_vci_cas_req = true;
4551        r_dcache_vci_paddr   = r_dcache_dirty_paddr.read();
4552        r_dcache_vci_cas_old = pte;
4553        r_dcache_vci_cas_new = pte | PTE_D_MASK;
4554        r_dcache_fsm         = DCACHE_DIRTY_WAIT;
4555
4556#if DEBUG_DCACHE
4557if ( m_debug_activated )
4558{
4559    std::cout << "  <PROC " << name()
4560              << " DCACHE_DIRTY_GET_PTE> CAS request" << std::hex
4561              << " / PTE_PADDR = " << r_dcache_dirty_paddr.read()
4562              << " / PTE_VALUE = " << pte << std::dec
4563              << " / SET = " << set
4564              << " / WAY = " << way << std::endl;
4565}
4566#endif
4567        break;
4568    }
4569    ///////////////////////
4570    case DCACHE_DIRTY_WAIT:         // wait completion of CAS for PTE Dirty bit,
4571                                    // and return to IDLE state when response is received.
4572                                    // we don't care if the CAS is a failure:
4573                                    // - if the CAS is a success, the coherence mechanism
4574                                    //   updates the local copy.
4575                                    // - if the CAS is a failure, we just retry the write.
4576    {
4577        // coherence clack request (from DSPIN CLACK)
4578        if ( r_dcache_clack_req.read() )
4579        {
4580            r_dcache_fsm = DCACHE_CC_CHECK;
4581            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4582            break;
4583        }
4584
4585        // coherence request (from CC_RECEIVE FSM)
4586        if ( r_cc_receive_dcache_req.read() and not r_dcache_cc_send_req.read())
4587        {
4588            r_dcache_fsm = DCACHE_CC_CHECK;
4589            r_dcache_fsm_cc_save = r_dcache_fsm.read();
4590            break;
4591        }
4592
4593        if ( r_vci_rsp_data_error.read() )      // bus error
4594        {
4595            std::cout << "BUS ERROR in DCACHE_DIRTY_WAIT state" << std::endl;
4596            std::cout << "This should not happen in this state" << std::endl;
4597            exit(0);
4598        }
4599        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
4600        {
4601            vci_rsp_fifo_dcache_get = true;
4602            r_dcache_fsm            = DCACHE_IDLE;
4603
4604#if DEBUG_DCACHE
4605if ( m_debug_activated )
4606{
4607    std::cout << "  <PROC " << name()
4608              << " DCACHE_DIRTY_WAIT> CAS completed" << std::endl;
4609}
4610#endif
4611        }
4612        break;
4613    }
4614    /////////////////////
4615    case DCACHE_CC_CHECK:   // This state is the entry point for the sub-FSM
4616                            // handling coherence requests for DCACHE.
4617                            // If there is a matching pending miss on the modified cache
4618                            // line this is signaled in the r_dcache_miss inval flip-flop.
4619                            // If the updated (or invalidated) cache line has copies in TLBs
4620                            // these TLB copies are invalidated.
4621                            // The return state is defined in r_dcache_fsm_cc_save
4622    {
4623        paddr_t  paddr = r_cc_receive_dcache_nline.read() * m_dcache_words * 4;
4624        paddr_t  mask = ~((m_dcache_words<<2)-1);
4625
4626#if DEBUG_DCACHE
4627if ( m_debug_activated )
4628{
4629    std::cout << "  <PROC " << name()
4630              << " DCACHE_CC_CHECK> paddr = " << paddr
4631              << " r_dcache_vci_paddr = " << r_dcache_vci_paddr.read()
4632              << " mask = " << mask
4633              << " (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) = " 
4634              << (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT)
4635              << " (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT) = " 
4636              << (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT)
4637              << " ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) = " 
4638              << ((r_dcache_vci_paddr.read() & mask) == (paddr & mask))
4639              <<std::endl;
4640}
4641#endif
4642        // CLACK handler
4643        // We switch the directory slot to EMPTY state and reset
4644        // r_dcache_miss_clack if the cleanup ack is matching a pending miss.
4645        if ( r_dcache_clack_req.read() )
4646        {
4647            if ( m_dreq.valid ) m_cost_data_miss_frz++;
4648
4649#ifdef INSTRUMENTATION
4650m_cpt_dcache_dir_write++;
4651#endif
4652            r_dcache.write_dir( 0,
4653                                r_dcache_clack_way.read(),
4654                                r_dcache_clack_set.read(),
4655                                CACHE_SLOT_STATE_EMPTY);
4656
4657            if ( (r_dcache_miss_set.read() == r_dcache_clack_set.read()) and
4658                 (r_dcache_miss_way.read() == r_dcache_clack_way.read()) )
4659            {
4660                  r_dcache_miss_clack = false;
4661            }
4662
4663            r_dcache_clack_req = false;
4664
4665            // return to cc_save state
4666            r_dcache_fsm = r_dcache_fsm_cc_save.read() ;
4667
4668#if DEBUG_DCACHE
4669if ( m_debug_activated )
4670{
4671    std::cout << "  <PROC " << name()
4672              << " DCACHE_CC_CHECK> CC_TYPE_CLACK Switch slot to EMPTY state"
4673              << " set = " << r_dcache_clack_set.read()
4674              << " / way = " << r_dcache_clack_way.read() << std::endl;
4675}
4676#endif
4677            break;
4678        }
4679
4680        assert ( not r_dcache_cc_send_req.read() and "CC_SEND must be available in DCACHE_CC_CHECK" );
4681
4682        // Match between MISS address and CC address
4683        if (r_cc_receive_dcache_req.read() and
4684          ((r_dcache_fsm_cc_save == DCACHE_MISS_SELECT  )  or
4685           (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT    )  or
4686           (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT)) and
4687          ((r_dcache_vci_paddr.read() & mask) == (paddr & mask))) // matching
4688        {
4689            // signaling matching
4690            r_dcache_miss_inval = true;
4691
4692            // in case of update, go to CC_UPDT
4693            // JUST TO POP THE FIFO
4694            if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)
4695            {
4696                r_dcache_fsm        = DCACHE_CC_UPDT;
4697                r_dcache_cc_word    = r_cc_receive_word_idx.read();
4698
4699                // just pop the fifo , don't write in icache
4700                r_dcache_cc_need_write = false;
4701            }
4702            // the request is dealt with
4703            else
4704            {
4705                r_cc_receive_dcache_req = false;
4706                r_dcache_fsm            = r_dcache_fsm_cc_save.read();
4707            }
4708
4709#if DEBUG_DCACHE
4710if ( m_debug_activated )
4711{
4712    std::cout << "  <PROC " << name()
4713              << " DCACHE_CC_CHECK> Coherence request matching a pending miss:"
4714              << " PADDR = " << std::hex << paddr << std::endl;
4715}
4716#endif
4717        }
4718
4719        // CC request handler
4720       
4721        int    state = 0;
4722        size_t way   = 0;
4723        size_t set   = 0;
4724        size_t word  = 0;
4725
4726#ifdef INSTRUMENTATION
4727m_cpt_dcache_dir_read++;
4728#endif
4729        r_dcache.read_dir( paddr,
4730                           &state,
4731                           &way,
4732                           &set,
4733                           &word ); // unused
4734
4735        r_dcache_cc_way = way;
4736        r_dcache_cc_set = set;
4737
4738        if ( state == CACHE_SLOT_STATE_VALID) // hit
4739        {
4740            // need to update the cache state
4741            if (r_cc_receive_dcache_type.read() == CC_TYPE_UPDT) // hit update
4742            {
4743                r_dcache_cc_need_write = true;
4744                r_dcache_fsm           = DCACHE_CC_UPDT;
4745                r_dcache_cc_word       = r_cc_receive_word_idx.read();
4746            }
4747            else if ( r_cc_receive_dcache_type.read() == CC_TYPE_INVAL ) // hit inval
4748            {
4749                r_dcache_fsm           = DCACHE_CC_INVAL;
4750            }
4751        }
4752        else                                  // miss
4753        {
4754            // multicast acknowledgement required in case of update
4755            if(r_cc_receive_dcache_type.read() == CC_TYPE_UPDT)
4756            {
4757                r_dcache_fsm           = DCACHE_CC_UPDT;
4758                r_dcache_cc_word       = r_cc_receive_word_idx.read();
4759
4760                // just pop the fifo , don't write in icache
4761                r_dcache_cc_need_write = false;
4762            }
4763            else // No response needed
4764            {
4765                r_cc_receive_dcache_req = false;
4766                r_dcache_fsm            = r_dcache_fsm_cc_save.read();
4767            }
4768        }
4769
4770#if DEBUG_DCACHE
4771if ( m_debug_activated )
4772{
4773    std::cout << "  <PROC " << name()
4774              << " DCACHE_CC_CHECK> Coherence request received:"
4775              << " PADDR = " << std::hex << paddr
4776              << " / TYPE = " << std::dec << r_cc_receive_dcache_type.read()
4777              << " / HIT = " << (state == CACHE_SLOT_STATE_VALID) << std::endl;
4778}
4779#endif
4780
4781        break;
4782    }
4783    /////////////////////
4784    case DCACHE_CC_INVAL: // hit inval: switch slot to ZOMBI state and send a
4785                          // CLEANUP after possible invalidation of copies in
4786                          // TLBs
4787    {
4788        size_t way    = r_dcache_cc_way.read();
4789        size_t set    = r_dcache_cc_set.read();
4790
4791        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )       // selective TLB inval
4792        {
4793            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4794            r_dcache_tlb_inval_line  = r_cc_receive_dcache_nline.read();
4795            r_dcache_tlb_inval_set   = 0;
4796            r_dcache_fsm_scan_save   = r_dcache_fsm.read();
4797            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4798            break;
4799        }
4800
4801        if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) // TLB flush
4802        {
4803            r_itlb.reset();
4804            r_dtlb.reset();
4805            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4806
4807#if DEBUG_DCACHE
4808if ( m_debug_activated )
4809{
4810    std::cout << "  <PROC " << name()
4811              << " DCACHE_CC_INVAL> Flush DTLB & ITLB" << std::endl;
4812}
4813#endif
4814        }
4815
4816        assert (not r_dcache_cc_send_req.read() &&
4817                "ERROR in DCACHE_CC_INVAL: the r_dcache_cc_send_req "
4818                "must not be set");
4819
4820        // Switch slot state to ZOMBI and send CLEANUP command
4821        r_dcache.write_dir( 0,
4822                            way,
4823                            set,
4824                            CACHE_SLOT_STATE_ZOMBI );
4825
4826        // coherence request completed
4827        r_cc_receive_dcache_req = false;
4828        r_dcache_cc_send_req    = true;
4829        r_dcache_cc_send_nline  = r_cc_receive_dcache_nline.read();
4830        r_dcache_cc_send_way    = r_dcache_cc_way.read();
4831        r_dcache_cc_send_type   = CC_TYPE_CLEANUP;
4832        r_dcache_fsm            = r_dcache_fsm_cc_save.read();
4833
4834#if DEBUG_DCACHE
4835if ( m_debug_activated )
4836{
4837    std::cout << "  <PROC " << name()
4838        << " DCACHE_CC_INVAL> Switch slot to EMPTY state:" << std::dec
4839        << " / WAY = " << way
4840        << " / SET = " << set << std::endl;
4841}
4842#endif
4843        break;
4844    }
4845    ///////////////////
4846    case DCACHE_CC_UPDT:        // hit update: write one word per cycle,
4847                                // after possible invalidation of copies in TLBs
4848    {
4849        size_t word       = r_dcache_cc_word.read();
4850        size_t way        = r_dcache_cc_way.read();
4851        size_t set        = r_dcache_cc_set.read();
4852
4853        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )       // selective TLB inval
4854        {
4855            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4856            r_dcache_tlb_inval_line = r_cc_receive_dcache_nline.read();
4857            r_dcache_tlb_inval_set  = 0;
4858            r_dcache_fsm_scan_save  = r_dcache_fsm.read();
4859            r_dcache_fsm            = DCACHE_INVAL_TLB_SCAN;
4860
4861            break;
4862        }
4863
4864        if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) // TLB flush
4865        {
4866            r_itlb.reset();
4867            r_dtlb.reset();
4868            r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
4869
4870#if DEBUG_DCACHE
4871if ( m_debug_activated )
4872{
4873    std::cout << "  <PROC " << name()
4874              << " DCACHE_CC_UPDT> Flush DTLB & ITLB" << std::endl;
4875}
4876#endif
4877        }
4878
4879        assert (not r_dcache_cc_send_req.read() &&
4880                "ERROR in DCACHE_CC_INVAL: the r_dcache_cc_send_req "
4881                "must not be set");
4882       
4883        if ( not r_cc_receive_updt_fifo_be.rok() ) break;
4884
4885        if (r_dcache_cc_need_write.read())
4886        {
4887       
4888#ifdef INSTRUMENTATION
4889m_cpt_dcache_data_write++;
4890#endif
4891            r_dcache.write( way,
4892                            set,
4893                            word,
4894                            r_cc_receive_updt_fifo_data.read(),
4895                            r_cc_receive_updt_fifo_be.read() );
4896
4897            r_dcache_cc_word = word + 1;
4898
4899#if DEBUG_DCACHE
4900if ( m_debug_activated )
4901{
4902    std::cout << "  <PROC " << name()
4903              << " DCACHE_CC_UPDT> Write one word" << std::dec
4904              << " / WAY = " << way
4905              << " / SET = " << set
4906              << " / WORD = " << word
4907              << " / VALUE = " << std::hex << r_cc_receive_updt_fifo_data.read() << std::endl;
4908}
4909#endif
4910        }
4911
4912        if ( r_cc_receive_updt_fifo_eop.read() )  // last word
4913        {
4914            // no need to write in the cache anymore
4915            r_dcache_cc_need_write = false;
4916
4917            // coherence request completed
4918            r_cc_receive_dcache_req = false;
4919
4920            // request multicast acknowledgement
4921            r_dcache_cc_send_req          = true;
4922            r_dcache_cc_send_nline        = r_cc_receive_dcache_nline.read();
4923            r_dcache_cc_send_updt_tab_idx = r_cc_receive_dcache_updt_tab_idx.read();
4924            r_dcache_cc_send_type         = CC_TYPE_MULTI_ACK;
4925
4926            r_dcache_fsm                  = r_dcache_fsm_cc_save.read();
4927        }
4928
4929        //consume fifo if not eop
4930        cc_receive_updt_fifo_get  = true;
4931
4932        break;
4933    }
4934    ///////////////////////////
4935    case DCACHE_INVAL_TLB_SCAN:         // Scan sequencially all sets for both ITLB & DTLB
4936                                        // It makes assumption: m_itlb_sets == m_dtlb_sets
4937                                        // All ways are handled in parallel.
4938                                        // We enter this state when a DCACHE line is modified,
4939                                        // and there is a copy in itlb or dtlb.
4940                                        // It can be caused by:
4941                                        // - a coherence inval or updt transaction,
4942                                        // - a line inval caused by a cache miss
4943                                        // - a processor XTN inval request,
4944                                        // - a WRITE hit,
4945                                        // - a Dirty bit update
4946                                        // Input arguments are:
4947                                        // - r_dcache_tlb_inval_line
4948                                        // - r_dcache_tlb_inval_set
4949                                        // - r_dcache_fsm_scan_save
4950    {
4951        paddr_t line = r_dcache_tlb_inval_line.read();
4952        size_t  set  = r_dcache_tlb_inval_set.read();
4953        size_t  way;
4954        bool    ok;
4955
4956        for ( way = 0 ; way < m_itlb_ways ; way++ )
4957        {
4958            ok = r_itlb.inval( line, way, set );
4959
4960#if DEBUG_DCACHE
4961if ( m_debug_activated and ok )
4962{
4963    std::cout << "  <PROC " << name()
4964              << ".DCACHE_INVAL_TLB_SCAN> Invalidate ITLB entry:" << std::hex
4965              << " line = " << line << std::dec
4966              << " / set = " << set
4967              << " / way = " << way << std::endl;
4968}
4969#endif
4970        }
4971
4972        for ( way = 0 ; way < m_dtlb_ways ; way++ )
4973        {
4974            ok = r_dtlb.inval( line, way, set );
4975
4976#if DEBUG_DCACHE
4977if ( m_debug_activated and ok )
4978std::cout << "  <PROC " << name() << " DCACHE_INVAL_TLB_SCAN>"
4979          << " Invalidate DTLB entry" << std::hex
4980          << " / line = " << line << std::dec
4981          << " / set = " << set
4982          << " / way = " << way << std::endl;
4983#endif
4984        }
4985
4986        // return to the calling state when TLB inval completed
4987        if ( r_dcache_tlb_inval_set.read() == (m_dtlb_sets-1) )
4988        {
4989            r_dcache_fsm = r_dcache_fsm_scan_save.read();
4990        }
4991        r_dcache_tlb_inval_set = r_dcache_tlb_inval_set.read() + 1;
4992        break;
4993    }
4994    } // end switch r_dcache_fsm
4995
4996    ///////////////// wbuf update ///////////////////////////////////////////////////////
4997    r_wbuf.update();
4998
4999    ///////////////// llsc update ///////////////////////////////////////////////////////
5000    if (r_dcache_llsc_valid.read()) r_dcache_llsc_count = r_dcache_llsc_count.read() - 1;
5001    if (r_dcache_llsc_count.read() == 1) r_dcache_llsc_valid = false;
5002
5003    //////////////// test processor frozen //////////////////////////////////////////////
5004    // The simulation exit if the number of consecutive frozen cycles
5005    // is larger than the m_max_frozen_cycles (constructor parameter)
5006    if ( (m_ireq.valid and not m_irsp.valid) or (m_dreq.valid and not m_drsp.valid) )
5007    {
5008        m_cpt_frz_cycles++;             // used for instrumentation
5009        m_cpt_stop_simulation++;        // used for debug
5010        if ( m_cpt_stop_simulation > m_max_frozen_cycles )
5011        {
5012            std::cout << std::dec << "ERROR in CC_VCACHE_WRAPPER " << name() << std::endl
5013                      << " stop at cycle " << m_cpt_total_cycles << std::endl
5014                      << " frozen since cycle " << m_cpt_total_cycles - m_max_frozen_cycles
5015                      << std::endl;
5016                      r_iss.dump();
5017            exit(1);
5018        }
5019    }
5020    else
5021    {
5022        m_cpt_stop_simulation = 0;
5023    }
5024
5025    /////////// execute one iss cycle /////////////////////////////////
5026    {
5027    uint32_t it = 0;
5028    for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if(p_irq[i].read()) it |= (1<<i);
5029    r_iss.executeNCycles(1, m_irsp, m_drsp, it);
5030    }
5031
5032    ////////////////////////////////////////////////////////////////////////////
5033    // The VCI_CMD FSM controls the following ressources:
5034    // - r_vci_cmd_fsm
5035    // - r_vci_cmd_min
5036    // - r_vci_cmd_max
5037    // - r_vci_cmd_cpt
5038    // - r_vci_cmd_imiss_prio
5039    // - wbuf (reset)
5040    // - r_icache_miss_req (reset)
5041    // - r_icache_unc_req (reset)
5042    // - r_dcache_vci_miss_req (reset)
5043    // - r_dcache_vci_unc_req (reset)
5044    // - r_dcache_vci_ll_req (reset)
5045    // - r_dcache_vci_sc_req (reset in case of local sc fail)
5046    // - r_dcache_vci_cas_req (reset)
5047    //
5048    // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
5049    // There are 8 request types, with the following priorities :
5050    // 1 - Data Read Miss         : r_dcache_vci_miss_req and miss in the write buffer
5051    // 2 - Data Read Uncachable   : r_dcache_vci_unc_req
5052    // 3 - Instruction Miss       : r_icache_miss_req and miss in the write buffer
5053    // 4 - Instruction Uncachable : r_icache_unc_req
5054    // 5 - Data Write             : r_wbuf.rok()
5055    // 6 - Data Linked Load       : r_dcache_vci_ll_req
5056    // 7 - Data Store Conditionnal: r_dcache_vci_sc_req
5057    // 8 - Compare And Swap       : r_dcache_vci_cas_req
5058    //
5059    // As we want to support several simultaneous VCI transactions, the VCI_CMD_FSM
5060    // and the VCI_RSP_FSM are fully desynchronized.
5061    //
5062    // VCI formats:
5063    // According to the VCI advanced specification, all read requests packets
5064    // (data Uncached, Miss data, instruction Uncached, Miss instruction)
5065    // are one word packets.
5066    // For write burst packets, all words are in the same cache line,
5067    // and addresses must be contiguous (the BE field is 0 in case of "holes").
5068    // The sc command packet implements actually a compare-and-swap mechanism
5069    // and the packet contains two flits.
5070    ////////////////////////////////////////////////////////////////////////////////////
5071
5072
5073    switch ( r_vci_cmd_fsm.read() )
5074    {
5075        //////////////
5076        case CMD_IDLE:
5077        {
5078            // DCACHE read requests (r_dcache_vci_miss_req or r_dcache_vci_ll_req), and
5079            // ICACHE read requests (r_icache_miss_req) require both a write_buffer access
5080            // to check a possible pending write on the same cache line.
5081            // As there is only one possible access per cycle to write buffer, we implement
5082            // a round-robin priority between DCACHE and ICACHE for this access,
5083            // using the r_vci_cmd_imiss_prio flip-flop.
5084
5085            size_t      wbuf_min;
5086            size_t      wbuf_max;
5087
5088            bool dcache_unc_req = r_dcache_vci_unc_req.read() and
5089                 ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() );
5090
5091            bool dcache_miss_req = r_dcache_vci_miss_req.read() and
5092                 ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() );
5093
5094            bool dcache_ll_req   = r_dcache_vci_ll_req.read() and
5095                 ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() );
5096
5097            bool icache_miss_req = r_icache_miss_req.read() and
5098                 ( not (r_dcache_vci_miss_req.read() or
5099                        r_dcache_vci_ll_req.read() or
5100                        r_dcache_vci_unc_req.read())
5101                     or r_vci_cmd_imiss_prio.read() );
5102
5103            // 1 - Data Read Miss
5104            if ( dcache_miss_req and r_wbuf.miss(r_dcache_vci_paddr.read()) )
5105            {
5106                r_vci_cmd_fsm         = CMD_DATA_MISS;
5107                r_dcache_vci_miss_req = false;
5108                r_vci_cmd_imiss_prio  = true;
5109//                m_cpt_dmiss_transaction++;
5110            }
5111            // 2 - Data Read Uncachable
5112            else if ( dcache_unc_req and r_wbuf.miss(r_dcache_vci_paddr.read()))
5113            {
5114                r_vci_cmd_fsm        = CMD_DATA_UNC;
5115                r_dcache_vci_unc_req = false;
5116//                m_cpt_dunc_transaction++;
5117            }
5118            // 3 - Data Linked Load
5119            else if ( dcache_ll_req and r_wbuf.miss(r_dcache_vci_paddr.read()))
5120            {
5121                r_dcache_vci_ll_req = false;
5122                r_vci_cmd_fsm       = CMD_DATA_LL;
5123//              m_cpt_ll_transaction++;
5124            }
5125            // 4 - Instruction Miss
5126            else if ( icache_miss_req and r_wbuf.miss(r_icache_vci_paddr.read()) )
5127            {
5128                r_vci_cmd_fsm        = CMD_INS_MISS;
5129                r_icache_miss_req    = false;
5130                r_vci_cmd_imiss_prio = false;
5131//                m_cpt_imiss_transaction++;
5132            }
5133            // 5 - Instruction Uncachable
5134            else if ( r_icache_unc_req.read() )
5135            {
5136                r_vci_cmd_fsm       = CMD_INS_UNC;
5137                r_icache_unc_req    = false;
5138//                m_cpt_iunc_transaction++;
5139            }
5140            // 6 - Data Write
5141            else if ( r_wbuf.rok(&wbuf_min, &wbuf_max) )
5142            {
5143                r_vci_cmd_fsm       = CMD_DATA_WRITE;
5144                r_vci_cmd_cpt       = wbuf_min;
5145                r_vci_cmd_min       = wbuf_min;
5146                r_vci_cmd_max       = wbuf_max;
5147//                m_cpt_write_transaction++;
5148//                m_length_write_transaction += (wbuf_max-wbuf_min+1);
5149            }
5150            // 7 - Data Store Conditionnal
5151            else if ( r_dcache_vci_sc_req.read() )
5152            {
5153                r_dcache_vci_sc_req = false;
5154                r_vci_cmd_cpt  = 0;
5155                r_vci_cmd_fsm  = CMD_DATA_SC;
5156//              m_cpt_sc_transaction++;
5157            }
5158            // 8 - Compare And Swap
5159            else if ( r_dcache_vci_cas_req.read() )
5160            {
5161                r_vci_cmd_fsm        = CMD_DATA_CAS;
5162                r_dcache_vci_cas_req = false;
5163                r_vci_cmd_cpt        = 0;
5164//              m_cpt_cas_transaction++;
5165            }
5166
5167#if DEBUG_CMD
5168if ( m_debug_activated )
5169{
5170std::cout << "  <PROC " << name() << " CMD_IDLE>"
5171          << " / dmiss_req = " << dcache_miss_req
5172          << " / imiss_req = " << icache_miss_req
5173          << std::endl;
5174}
5175#endif
5176            break;
5177        }
5178        ////////////////////
5179        case CMD_DATA_WRITE:
5180        {
5181            if ( p_vci.cmdack.read() )
5182            {
5183                r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
5184                if (r_vci_cmd_cpt == r_vci_cmd_max) // last flit sent
5185                {
5186                    r_vci_cmd_fsm = CMD_IDLE ;
5187                    r_wbuf.sent() ;
5188                }
5189            }
5190            break;
5191        }
5192        /////////////////
5193        case CMD_DATA_SC:
5194        case CMD_DATA_CAS:
5195        {
5196            // The CAS and SC VCI commands contain two flits
5197            if ( p_vci.cmdack.read() )
5198            {
5199               r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
5200               if (r_vci_cmd_cpt == 1) r_vci_cmd_fsm = CMD_IDLE ;
5201            }
5202            break;
5203        }
5204        //////////////////
5205        case CMD_INS_MISS:
5206        case CMD_INS_UNC:
5207        case CMD_DATA_MISS:
5208        case CMD_DATA_UNC:
5209        case CMD_DATA_LL:
5210        {
5211            // all read VCI commands contain one single flit
5212            if ( p_vci.cmdack.read() ) {
5213                r_vci_cmd_fsm = CMD_IDLE;
5214            }
5215            break;
5216        }
5217
5218    } // end  switch r_vci_cmd_fsm
5219
5220    //////////////////////////////////////////////////////////////////////////
5221    // The VCI_RSP FSM controls the following ressources:
5222    // - r_vci_rsp_fsm:
5223    // - r_vci_rsp_fifo_icache (push)
5224    // - r_vci_rsp_fifo_dcache (push)
5225    // - r_vci_rsp_data_error (set)
5226    // - r_vci_rsp_ins_error (set)
5227    // - r_vci_rsp_cpt
5228    // - r_dcache_vci_sc_req (reset when SC response recieved)
5229    //
5230    // As the VCI_RSP and VCI_CMD are fully desynchronized to support several
5231    // simultaneous VCI transactions, this FSM uses the VCI RPKTID field
5232    // to identify the transactions.
5233    //
5234    // VCI vormat:
5235    // This component checks the response packet length and accepts only
5236    // single word packets for write response packets.
5237    //
5238    // Error handling:
5239    // This FSM analyzes the VCI error code and signals directly the Write Bus Error.
5240    // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error
5241    // flip_flop and the error is signaled by the DCACHE FSM.
5242    // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
5243    // flip_flop and the error is signaled by the ICACHE FSM.
5244    // In case of Cleanup Error, the simulation stops with an error message...
5245    //////////////////////////////////////////////////////////////////////////
5246
5247    switch ( r_vci_rsp_fsm.read() )
5248    {
5249    //////////////
5250    case RSP_IDLE:
5251    {
5252        if ( p_vci.rspval.read() )
5253        {
5254            r_vci_rsp_cpt = 0;
5255
5256            if      ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_DATA_UNC  )
5257            {
5258                r_vci_rsp_fsm = RSP_DATA_UNC;
5259            }
5260            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_DATA_MISS )
5261            {
5262                r_vci_rsp_fsm = RSP_DATA_MISS;
5263            }
5264            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_INS_UNC   )
5265            {
5266                r_vci_rsp_fsm = RSP_INS_UNC;
5267            }
5268            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_READ_INS_MISS  )
5269            {
5270                r_vci_rsp_fsm = RSP_INS_MISS;
5271            }
5272            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_WRITE          )
5273            {
5274                r_vci_rsp_fsm = RSP_DATA_WRITE;
5275            }
5276            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_CAS            )
5277            {
5278                r_vci_rsp_fsm = RSP_DATA_UNC;
5279            }
5280            else if ( (p_vci.rpktid.read() & 0x7) ==  TYPE_LL             )
5281            {
5282                r_vci_rsp_fsm = RSP_DATA_LL;
5283            }
5284            else if ( (p_vci.rpktid.read() & 0x7) == TYPE_SC             )
5285            {
5286                r_vci_rsp_fsm = RSP_DATA_UNC;
5287            }
5288            else
5289            {
5290                assert(false and "Unexpected VCI response");
5291            }
5292        }
5293        break;
5294    }
5295        //////////////////
5296        case RSP_INS_MISS:
5297        {
5298            if ( p_vci.rspval.read() )
5299            {
5300                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5301                {
5302                    r_vci_rsp_ins_error = true;
5303                    if ( p_vci.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
5304                }
5305                else                                        // no error reported
5306                {
5307                    if ( r_vci_rsp_fifo_icache.wok() )
5308                    {
5309                        if ( r_vci_rsp_cpt.read() >= m_icache_words )
5310                        {
5311                            std::cout << "ERROR in VCI_CC_VCACHE " << name()
5312                                      << " VCI response packet too long "
5313                                      << " for instruction miss" << std::endl;
5314                            exit(0);
5315                        }
5316                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
5317                        vci_rsp_fifo_icache_put       = true,
5318                        vci_rsp_fifo_icache_data      = p_vci.rdata.read();
5319                        if ( p_vci.reop.read() )
5320                        {
5321                            if ( r_vci_rsp_cpt.read() != (m_icache_words - 1) )
5322                            {
5323                                std::cout << "ERROR in VCI_CC_VCACHE " << name()
5324                                          << " VCI response packet too short" 
5325                                          << " for instruction miss" << std::endl;
5326                                exit(0);
5327                            }
5328                            r_vci_rsp_fsm    = RSP_IDLE;
5329                        }
5330                    }
5331                }
5332            }
5333            break;
5334        }
5335        /////////////////
5336        case RSP_INS_UNC:
5337        {
5338            if (p_vci.rspval.read() )
5339            {
5340                assert( p_vci.reop.read() and
5341                "illegal VCI response packet for uncachable instruction");
5342
5343                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5344                {
5345                    r_vci_rsp_ins_error = true;
5346                    r_vci_rsp_fsm = RSP_IDLE;
5347                }
5348                else                                         // no error reported
5349                {
5350                    if ( r_vci_rsp_fifo_icache.wok())
5351                    {
5352                        vci_rsp_fifo_icache_put       = true;
5353                        vci_rsp_fifo_icache_data      = p_vci.rdata.read();
5354                        r_vci_rsp_fsm = RSP_IDLE;
5355                    }
5356                }
5357            }
5358            break;
5359        }
5360        ///////////////////
5361        case RSP_DATA_MISS:
5362        {
5363            if ( p_vci.rspval.read() )
5364            {
5365                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5366                {
5367                    r_vci_rsp_data_error = true;
5368                    if ( p_vci.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
5369                }
5370                else                                        // no error reported
5371                {
5372                    if ( r_vci_rsp_fifo_dcache.wok() )
5373                    {
5374                        assert( (r_vci_rsp_cpt.read() < m_dcache_words) and
5375                        "The VCI response packet for data miss is too long");
5376
5377                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
5378                        vci_rsp_fifo_dcache_put       = true,
5379                        vci_rsp_fifo_dcache_data      = p_vci.rdata.read();
5380                        if ( p_vci.reop.read() )
5381                        {
5382                            assert( (r_vci_rsp_cpt.read() == m_dcache_words - 1) and
5383                            "The VCI response packet for data miss is too short");
5384
5385                            r_vci_rsp_fsm     = RSP_IDLE;
5386                        }
5387                    }
5388                }
5389            }
5390            break;
5391        }
5392        //////////////////
5393        case RSP_DATA_UNC:
5394        {
5395            if (p_vci.rspval.read() )
5396            {
5397                assert( p_vci.reop.read() and
5398                "illegal VCI response packet for uncachable read data");
5399
5400                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5401                {
5402                    r_vci_rsp_data_error = true;
5403                    r_vci_rsp_fsm = RSP_IDLE;
5404                }
5405                else                                         // no error reported
5406                {
5407                    if ( r_vci_rsp_fifo_dcache.wok())
5408                    {
5409                        vci_rsp_fifo_dcache_put       = true;
5410                        vci_rsp_fifo_dcache_data      = p_vci.rdata.read();
5411                        r_vci_rsp_fsm = RSP_IDLE;
5412                    }
5413                }
5414            }
5415            break;
5416        }
5417        /////////////////
5418        case RSP_DATA_LL:
5419        {
5420            if ( p_vci.rspval.read() )
5421            {
5422                if ( (p_vci.rerror.read()&0x1) != 0 )  // error reported
5423                {
5424                    r_vci_rsp_data_error = true;
5425                    r_vci_rsp_fsm = RSP_IDLE;
5426                    break;
5427                }
5428                if (r_vci_rsp_cpt.read() == 0) //first flit
5429                {
5430                    if(r_vci_rsp_fifo_dcache.wok())
5431                    {
5432                        assert(!p_vci.reop.read() &&
5433                            "illegal VCI response packet for LL");
5434                        vci_rsp_fifo_dcache_put  = true;
5435                        vci_rsp_fifo_dcache_data = p_vci.rdata.read();
5436                        r_vci_rsp_cpt            = r_vci_rsp_cpt.read() + 1;
5437                    }
5438                    break;
5439                }
5440                else // last flit
5441                {
5442                    if(r_vci_rsp_fifo_dcache.wok())
5443                    {
5444                        assert(p_vci.reop.read() &&
5445                            "illegal VCI response packet for LL");
5446                        vci_rsp_fifo_dcache_put  = true;
5447                        vci_rsp_fifo_dcache_data = p_vci.rdata.read();
5448                        r_vci_rsp_fsm            = RSP_IDLE;
5449                    }
5450                    break;
5451                }
5452            }
5453            break;
5454        }
5455        ////////////////////
5456        case RSP_DATA_WRITE:
5457        {
5458            if (p_vci.rspval.read())
5459            {
5460                assert( p_vci.reop.read() and
5461                "a VCI response packet must contain one flit for a write transaction");
5462
5463                r_vci_rsp_fsm = RSP_IDLE;
5464                uint32_t   wbuf_index = p_vci.rtrdid.read();
5465                bool       cacheable  = r_wbuf.completed(wbuf_index);
5466                if ( not cacheable ) r_dcache_pending_unc_write = false;
5467                if ( (p_vci.rerror.read()&0x1) != 0 ) r_iss.setWriteBerr();
5468            }
5469            break;
5470        }
5471    } // end switch r_vci_rsp_fsm
5472
5473    /////////////////////////////////////////////////////////////////////////////////////
5474    // The CC_SEND FSM is in charge of sending cleanups and the multicast
5475    // acknowledgements on the coherence network. It has two clients (DCACHE FSM
5476    // and ICACHE FSM) that are served with a round-robin priority.
5477    // The CC_SEND FSM resets the r_*cache_cc_send_req request flip-flops as
5478    // soon as the request has been sent.
5479    /////////////////////////////////////////////////////////////////////////////////////
5480    switch ( r_cc_send_fsm.read() )
5481    {
5482        ///////////////////////////
5483        case CC_SEND_IDLE:
5484        {
5485            ///////////////////////////////////////////////////////
5486            // handling round robin between icache and dcache :  //
5487            // we first check for the last client and listen for //
5488            // a request of the other, then update the client    //
5489            // r_cc_send_last_client : 0 dcache / 1 icache
5490            ///////////////////////////////////////////////////////
5491            bool update_last_client = r_cc_send_last_client.read();
5492            if ( r_cc_send_last_client.read() == 0 ) // last client was dcache
5493            {
5494                if (r_icache_cc_send_req.read()) // request from icache
5495                    update_last_client = 1; // update last client to icache
5496            }
5497            else // last client was icache
5498            {
5499                if (r_dcache_cc_send_req.read()) // request from dcache
5500                    update_last_client = 0; // update last client to dcache
5501            }
5502            r_cc_send_last_client = update_last_client;
5503
5504            // if there is an actual request
5505            if (r_dcache_cc_send_req.read() or r_icache_cc_send_req.read())
5506            {
5507                // the new client is dcache and has a cleanup request
5508                if      ( (update_last_client == 0) and
5509                          (r_dcache_cc_send_type.read() == CC_TYPE_CLEANUP))
5510                    r_cc_send_fsm = CC_SEND_CLEANUP_1;
5511                // the new client is dcache and has a multi acknowledgement request
5512                else if ( (update_last_client == 0) and
5513                          (r_dcache_cc_send_type.read() == CC_TYPE_MULTI_ACK))
5514                    r_cc_send_fsm = CC_SEND_MULTI_ACK;
5515                // the new client is icache and has a cleanup request
5516                else if ( (update_last_client == 1) and
5517                          (r_icache_cc_send_type.read() == CC_TYPE_CLEANUP))
5518                    r_cc_send_fsm = CC_SEND_CLEANUP_1;
5519                // the new client is icache and has a multi acknowledgement request
5520                else if ( (update_last_client == 1) and
5521                        (r_icache_cc_send_type.read() == CC_TYPE_MULTI_ACK))
5522                    r_cc_send_fsm = CC_SEND_MULTI_ACK;
5523            }
5524            break;
5525        }
5526        ///////////////////////////
5527        case CC_SEND_CLEANUP_1:
5528        {
5529            // wait for the first flit to be consumed
5530            if (p_dspin_p2m.read.read())
5531                r_cc_send_fsm = CC_SEND_CLEANUP_2;
5532
5533            break;
5534        }
5535        ///////////////////////////
5536        case CC_SEND_CLEANUP_2:
5537        {
5538            // wait for the second flit to be consumed
5539            if (p_dspin_p2m.read.read())
5540            {
5541                if (r_cc_send_last_client.read() == 0) // dcache active request
5542                    r_dcache_cc_send_req = false; // reset dcache request
5543                else // icache active request
5544                    r_icache_cc_send_req = false; // reset icache request
5545
5546                // go back to idle state
5547                r_cc_send_fsm = CC_SEND_IDLE;
5548            }
5549            break;
5550        }
5551        ///////////////////////////
5552        case CC_SEND_MULTI_ACK:
5553        {
5554            // wait for the 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                // go back to idle state
5562                r_cc_send_fsm = CC_SEND_IDLE;
5563            }
5564            break;
5565        }
5566    } // end switch CC_SEND FSM
5567
5568    ///////////////////////////////////////////////////////////////////////////////
5569    //  CC_RECEIVE  FSM
5570    // This FSM receive all coherence packets on a DSPIN40 port.
5571    // There is 5 packet types:
5572    // - CC_DATA_INVAL : DCACHE invalidate request
5573    // - CC_DATA_UPDT  : DCACHE update request (multi-words)
5574    // - CC_INST_INVAL : ICACHE invalidate request
5575    // - CC_INST_UPDT  : ICACHE update request (multi-words)
5576    // - CC_BROADCAST  : Broadcast invalidate request (both DCACHE & ICACHE)
5577    //////////////////////////////////////////////////////////////////////////////
5578    switch( r_cc_receive_fsm.read() )
5579    {
5580        /////////////////////
5581        case CC_RECEIVE_IDLE:
5582        {
5583            // a coherence request has arrived
5584            if (p_dspin_m2p.write.read())
5585            {
5586                // initialize dspin received data
5587                uint64_t receive_data = p_dspin_m2p.data.read();
5588                // initialize coherence packet type
5589                uint64_t receive_type = DspinDhccpParam::dspin_get(receive_data,
5590                                            DspinDhccpParam::M2P_TYPE);
5591                // test for a broadcast
5592                if (DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::M2P_BC))
5593                {
5594                    r_cc_receive_fsm = CC_RECEIVE_BRDCAST_HEADER;
5595                }
5596                // test for a multi updt
5597                else if (receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_DATA) 
5598                {
5599                    r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_HEADER;
5600                }
5601                else if (receive_type == DspinDhccpParam::TYPE_MULTI_UPDT_INST)
5602                {
5603                    r_cc_receive_fsm = CC_RECEIVE_INS_UPDT_HEADER;
5604                }
5605                // test for a multi inval
5606                else if (receive_type == DspinDhccpParam::TYPE_MULTI_INVAL_DATA)
5607                {
5608                    r_cc_receive_fsm = CC_RECEIVE_DATA_INVAL_HEADER;
5609                }
5610                else
5611                {
5612                    r_cc_receive_fsm = CC_RECEIVE_INS_INVAL_HEADER;
5613                }
5614            }
5615            break;
5616        }
5617        ///////////////////////////////
5618        case CC_RECEIVE_BRDCAST_HEADER:
5619        {
5620            // no actual data in the HEADER, just skip to second flit
5621            r_cc_receive_fsm = CC_RECEIVE_BRDCAST_NLINE;
5622            break;
5623        }
5624        //////////////////////////////
5625        case CC_RECEIVE_BRDCAST_NLINE:
5626        {
5627            // initialize dspin received data
5628            uint64_t receive_data = p_dspin_m2p.data.read();
5629            // wait for both dcache and icache to take the request
5630            // TODO maybe we need to wait for both only to leave the state, but
5631            // not to actually post a request to an available cache => need a
5632            // flip_flop to check that ?
5633            if (not (r_cc_receive_icache_req.read()) and
5634                not (r_cc_receive_dcache_req.read()) and
5635                (p_dspin_m2p.write.read()))
5636            {
5637                // request dcache to handle the BROADCAST
5638                r_cc_receive_dcache_req = true;
5639                r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,
5640                                             DspinDhccpParam::BROADCAST_NLINE);
5641                r_cc_receive_dcache_type = CC_TYPE_INVAL;
5642                // request icache to handle the BROADCAST
5643                r_cc_receive_icache_req = true;
5644                r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,
5645                                             DspinDhccpParam::BROADCAST_NLINE);
5646                r_cc_receive_icache_type = CC_TYPE_INVAL;
5647                // get back to idle state
5648                r_cc_receive_fsm = CC_RECEIVE_IDLE;
5649                break;
5650            }
5651            // keep waiting for the caches to accept the request
5652            break;
5653        }
5654        /////////////////////////////
5655        case CC_RECEIVE_DATA_INVAL_HEADER:
5656        {
5657            // sample updt tab index in the HEADER, then skip to second flit
5658            r_cc_receive_fsm = CC_RECEIVE_DATA_INVAL_NLINE;
5659            break;
5660        }
5661        /////////////////////////////
5662        case CC_RECEIVE_INS_INVAL_HEADER:
5663        {
5664            // sample updt tab index in the HEADER, then skip to second flit
5665            r_cc_receive_fsm = CC_RECEIVE_INS_INVAL_NLINE;
5666            break;
5667        }
5668        ////////////////////////////
5669        case CC_RECEIVE_DATA_INVAL_NLINE:
5670        {
5671            // sample nline in the second flit
5672            uint64_t receive_data = p_dspin_m2p.data.read();
5673            // for data INVAL, wait for dcache to take the request
5674            if (p_dspin_m2p.write.read()           and
5675                not r_cc_receive_dcache_req.read() )
5676            {
5677                // request dcache to handle the INVAL
5678                r_cc_receive_dcache_req = true;
5679                r_cc_receive_dcache_nline = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
5680                r_cc_receive_dcache_type = CC_TYPE_INVAL;
5681                // get back to idle state
5682                r_cc_receive_fsm = CC_RECEIVE_IDLE;
5683                break;
5684            }
5685            break;
5686        }
5687        //////////////////////////////
5688        case CC_RECEIVE_INS_INVAL_NLINE:
5689        {
5690            // sample nline in the second flit
5691            uint64_t receive_data = p_dspin_m2p.data.read();
5692            // for ins INVAL, wait for icache to take the request
5693            if (p_dspin_m2p.write.read()           and
5694                not r_cc_receive_icache_req.read() )
5695            {
5696                // request icache to handle the INVAL
5697                r_cc_receive_icache_req = true;
5698                r_cc_receive_icache_nline = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_INVAL_NLINE);
5699                r_cc_receive_icache_type = CC_TYPE_INVAL;
5700                // get back to idle state
5701                r_cc_receive_fsm = CC_RECEIVE_IDLE;
5702                break;
5703            }
5704            break;
5705        }
5706        ////////////////////////////
5707        case CC_RECEIVE_DATA_UPDT_HEADER:
5708        {
5709            // sample updt tab index in the HEADER, than skip to second flit
5710            uint64_t receive_data = p_dspin_m2p.data.read();
5711            // for data INVAL, wait for dcache to take the request and fifo to
5712            // be empty
5713            if (not r_cc_receive_dcache_req.read())
5714            {
5715                r_cc_receive_dcache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
5716                r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_NLINE;
5717                break;
5718            }
5719            break;
5720        }
5721        ////////////////////////////
5722        case CC_RECEIVE_INS_UPDT_HEADER:
5723        {
5724            // sample updt tab index in the HEADER, than skip to second flit
5725            uint64_t receive_data = p_dspin_m2p.data.read();
5726            // for ins INVAL, wait for icache to take the request and fifo to be
5727            // empty
5728            if (not r_cc_receive_icache_req.read())
5729            {
5730                r_cc_receive_icache_updt_tab_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
5731                r_cc_receive_fsm = CC_RECEIVE_INS_UPDT_NLINE;
5732                break;
5733            }
5734            // keep waiting for the correct cache to accept the request
5735            break;
5736        }
5737        ///////////////////////////
5738        case CC_RECEIVE_DATA_UPDT_NLINE:
5739        {
5740            // sample nline and word index in the second flit
5741            uint64_t receive_data = p_dspin_m2p.data.read();
5742            // for data INVAL, wait for dcache to take the request and fifo to
5743            // be empty
5744            if ( r_cc_receive_updt_fifo_be.empty() and
5745                 p_dspin_m2p.write.read() )
5746            {
5747                r_cc_receive_dcache_req = true;
5748                r_cc_receive_dcache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_NLINE);
5749                r_cc_receive_word_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
5750                r_cc_receive_dcache_type = CC_TYPE_UPDT;
5751                // get back to idle state
5752                r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_DATA;
5753                break;
5754            }
5755            break;
5756        }
5757        ////////////////////////////
5758        case CC_RECEIVE_INS_UPDT_NLINE:
5759        {
5760            // sample nline and word index in the second flit
5761            uint64_t receive_data = p_dspin_m2p.data.read();
5762            // for ins INVAL, wait for icache to take the request and fifo to be
5763            // empty
5764            if ( r_cc_receive_updt_fifo_be.empty() and
5765                 p_dspin_m2p.write.read() )
5766            {
5767                r_cc_receive_icache_req = true;
5768                r_cc_receive_icache_nline  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_NLINE);
5769                r_cc_receive_word_idx  = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
5770                r_cc_receive_icache_type = CC_TYPE_UPDT;
5771                // get back to idle state
5772                r_cc_receive_fsm = CC_RECEIVE_INS_UPDT_DATA;
5773                break;
5774            }
5775            break;
5776        }
5777        //////////////////////////
5778        case CC_RECEIVE_DATA_UPDT_DATA:
5779        {
5780            // wait for the fifo
5781            if (r_cc_receive_updt_fifo_be.wok() and (p_dspin_m2p.write.read()))
5782            {
5783                uint64_t receive_data = p_dspin_m2p.data.read();
5784                bool     receive_eop  = p_dspin_m2p.eop.read();
5785                cc_receive_updt_fifo_be   = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_BE);
5786                cc_receive_updt_fifo_data = DspinDhccpParam::dspin_get(receive_data,DspinDhccpParam::MULTI_UPDT_DATA);
5787                cc_receive_updt_fifo_eop  = receive_eop;
5788                cc_receive_updt_fifo_put  = true;
5789                if ( receive_eop ) r_cc_receive_fsm = CC_RECEIVE_IDLE;
5790            }
5791            break;
5792        }
5793        //////////////////////////
5794        case CC_RECEIVE_INS_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    } // end switch CC_RECEIVE FSM
5811
5812    ///////////////// DSPIN CLACK interface ///////////////
5813   
5814    uint64_t clack_type = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
5815                                                     DspinDhccpParam::CLACK_TYPE);
5816
5817    size_t clack_way  = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
5818                                                   DspinDhccpParam::CLACK_WAY);
5819
5820    size_t clack_set  = DspinDhccpParam::dspin_get(r_dspin_clack_flit.read(),
5821                                                   DspinDhccpParam::CLACK_SET);
5822
5823    bool dspin_clack_get      = false;
5824    bool dcache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_DATA);
5825    bool icache_clack_request = (clack_type == DspinDhccpParam::TYPE_CLACK_INST);
5826
5827    if (r_dspin_clack_req.read())
5828    {
5829        // CLACK DATA: Send request to DCACHE FSM
5830        if (dcache_clack_request and not r_dcache_clack_req.read()){
5831            r_dcache_clack_req = true;
5832            r_dcache_clack_way = clack_way & ((1ULL<<(uint32_log2(m_dcache_ways)))-1);
5833            r_dcache_clack_set = clack_set & ((1ULL<<(uint32_log2(m_dcache_sets)))-1);
5834            dspin_clack_get    = true;
5835        }
5836
5837        // CLACK INST: Send request to ICACHE FSM
5838        else if (icache_clack_request and not r_icache_clack_req.read()){
5839            r_icache_clack_req = true;
5840            r_icache_clack_way = clack_way & ((1ULL<<(uint32_log2(m_dcache_ways)))-1);
5841            r_icache_clack_set = clack_set & ((1ULL<<(uint32_log2(m_icache_sets)))-1);
5842            dspin_clack_get    = true;
5843        }
5844    }
5845    else
5846    {
5847        dspin_clack_get = true;
5848    }
5849
5850    if (dspin_clack_get)
5851    {
5852        r_dspin_clack_req  = p_dspin_clack.write.read();
5853        r_dspin_clack_flit = p_dspin_clack.data.read();
5854    }
5855
5856    ///////////////// Response FIFOs update  //////////////////////
5857    r_vci_rsp_fifo_icache.update(vci_rsp_fifo_icache_get,
5858                                 vci_rsp_fifo_icache_put,
5859                                 vci_rsp_fifo_icache_data);
5860
5861    r_vci_rsp_fifo_dcache.update(vci_rsp_fifo_dcache_get,
5862                                 vci_rsp_fifo_dcache_put,
5863                                 vci_rsp_fifo_dcache_data);
5864
5865    ///////////////// updt FIFO update  //////////////////////
5866    //TODO check this
5867    r_cc_receive_updt_fifo_be.update(cc_receive_updt_fifo_get,
5868                                 cc_receive_updt_fifo_put,
5869                                 cc_receive_updt_fifo_be);
5870    r_cc_receive_updt_fifo_data.update(cc_receive_updt_fifo_get,
5871                                 cc_receive_updt_fifo_put,
5872                                 cc_receive_updt_fifo_data);
5873    r_cc_receive_updt_fifo_eop.update(cc_receive_updt_fifo_get,
5874                                 cc_receive_updt_fifo_put,
5875                                 cc_receive_updt_fifo_eop);
5876
5877} // end transition()
5878
5879///////////////////////
5880tmpl(void)::genMoore()
5881///////////////////////
5882{
5883
5884    // VCI initiator command on the direct network
5885    // it depends on the CMD FSM state
5886
5887    bool is_sc_or_cas  = (r_vci_cmd_fsm.read() == CMD_DATA_CAS) or
5888                         (r_vci_cmd_fsm.read() == CMD_DATA_SC );
5889
5890    p_vci.pktid  = 0;
5891    p_vci.srcid  = m_srcid;
5892    p_vci.cons   = is_sc_or_cas; 
5893    p_vci.contig = not is_sc_or_cas; 
5894    p_vci.wrap   = false;
5895    p_vci.clen   = 0;
5896    p_vci.cfixed = false;
5897
5898    if ( m_monitor_ok ) {
5899        if ( p_vci.cmdack.read() == true and p_vci.cmdval == true) {
5900            if (((p_vci.address.read()) >= m_monitor_base) and
5901                ((p_vci.address.read()) < m_monitor_base + m_monitor_length) ) {
5902                std::cout << "CC_VCACHE Monitor " << name() << std::hex
5903                          << " Access type = " << vci_cmd_type_str[p_vci.cmd.read()] 
5904                          << " Pktid type = " << vci_pktid_type_str[p_vci.pktid.read()]
5905                          << " : address = " << p_vci.address.read()
5906                          << " / be = " << p_vci.be.read(); 
5907                if ( p_vci.cmd.read() == vci_param::CMD_WRITE ) {
5908                    std::cout << " / data = " << p_vci.wdata.read();
5909                }
5910                std::cout << std::dec << std::endl;
5911            }
5912        }
5913    }
5914
5915    switch ( r_vci_cmd_fsm.read() ) {
5916
5917    case CMD_IDLE:
5918        p_vci.cmdval  = false;
5919        p_vci.address = 0;
5920        p_vci.wdata   = 0;
5921        p_vci.be      = 0;
5922        p_vci.trdid   = 0;
5923        p_vci.pktid   = 0;
5924        p_vci.plen    = 0;
5925        p_vci.cmd     = vci_param::CMD_NOP;
5926        p_vci.eop     = false;
5927        break;
5928
5929    case CMD_INS_MISS:
5930        p_vci.cmdval  = true;
5931        p_vci.address = r_icache_vci_paddr.read() & m_icache_yzmask;
5932        p_vci.wdata   = 0;
5933        p_vci.be      = 0xF;
5934        p_vci.trdid   = 0;
5935        p_vci.pktid   = TYPE_READ_INS_MISS;
5936        p_vci.plen    = m_icache_words<<2;
5937        p_vci.cmd     = vci_param::CMD_READ;
5938        p_vci.eop     = true;
5939        break;
5940
5941    case CMD_INS_UNC:
5942        p_vci.cmdval  = true;
5943        p_vci.address = r_icache_vci_paddr.read() & ~0x3;
5944        p_vci.wdata   = 0;
5945        p_vci.be      = 0xF;
5946        p_vci.trdid   = 0;
5947        p_vci.pktid   = TYPE_READ_INS_UNC;
5948        p_vci.plen    = 4;
5949        p_vci.cmd     = vci_param::CMD_READ;
5950        p_vci.eop     = true;
5951        break;
5952
5953    case CMD_DATA_MISS:
5954        p_vci.cmdval  = true;
5955        p_vci.address = r_dcache_vci_paddr.read() & m_dcache_yzmask;
5956        p_vci.wdata   = 0;
5957        p_vci.be      = 0xF;
5958        p_vci.trdid   = 0;
5959        p_vci.pktid   = TYPE_READ_DATA_MISS;
5960        p_vci.plen    = m_dcache_words << 2;
5961        p_vci.cmd     = vci_param::CMD_READ;
5962        p_vci.eop     = true;
5963        break;
5964
5965    case CMD_DATA_UNC:
5966        p_vci.cmdval  = true;
5967        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
5968        p_vci.wdata   = 0;
5969        p_vci.be      = r_dcache_vci_unc_be.read();
5970        p_vci.trdid   = 0;
5971        p_vci.pktid   = TYPE_READ_DATA_UNC;
5972        p_vci.plen    = 4;
5973        p_vci.cmd     = vci_param::CMD_READ;
5974        p_vci.eop     = true;
5975        break;
5976
5977    case CMD_DATA_WRITE:
5978        p_vci.cmdval  = true;
5979        p_vci.address = r_wbuf.getAddress(r_vci_cmd_cpt.read()) & ~0x3;
5980        p_vci.wdata   = r_wbuf.getData(r_vci_cmd_cpt.read());
5981        p_vci.be      = r_wbuf.getBe(r_vci_cmd_cpt.read());
5982        p_vci.trdid   = r_wbuf.getIndex();
5983        p_vci.pktid   = TYPE_WRITE;
5984        p_vci.plen    = (r_vci_cmd_max.read() - r_vci_cmd_min.read() + 1) << 2;
5985        p_vci.cmd     = vci_param::CMD_WRITE;
5986        p_vci.eop     = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
5987        break;
5988
5989    case CMD_DATA_LL:
5990        p_vci.cmdval  = true;
5991        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
5992        p_vci.wdata   = 0;
5993        p_vci.be      = 0xF;
5994        p_vci.trdid   = 0;
5995        p_vci.pktid   = TYPE_LL;
5996        p_vci.plen    = 8;
5997        p_vci.cmd     = vci_param::CMD_LOCKED_READ;
5998        p_vci.eop     = true;
5999        break;
6000
6001    case CMD_DATA_SC:
6002        p_vci.cmdval  = true;
6003        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
6004        if ( r_vci_cmd_cpt.read() == 0 ) p_vci.wdata = r_dcache_llsc_key.read();
6005        else                             p_vci.wdata = r_dcache_vci_sc_data.read();
6006        p_vci.be      = 0xF;
6007        p_vci.trdid   = 0;
6008        p_vci.pktid   = TYPE_SC;
6009        p_vci.plen    = 8;
6010        p_vci.cmd     = vci_param::CMD_NOP;
6011        p_vci.eop     = (r_vci_cmd_cpt.read() == 1);
6012        break;
6013
6014    case CMD_DATA_CAS:
6015        p_vci.cmdval  = true;
6016        p_vci.address = r_dcache_vci_paddr.read() & ~0x3;
6017        if ( r_vci_cmd_cpt.read() == 0 ) p_vci.wdata = r_dcache_vci_cas_old.read();
6018        else                             p_vci.wdata = r_dcache_vci_cas_new.read();
6019        p_vci.be      = 0xF;
6020        p_vci.trdid   = 0;
6021        p_vci.pktid   = TYPE_CAS;
6022        p_vci.plen    = 8;
6023        p_vci.cmd     = vci_param::CMD_NOP;
6024        p_vci.eop     = (r_vci_cmd_cpt.read() == 1);
6025        break;
6026    } // end switch r_vci_cmd_fsm
6027
6028    // VCI initiator response on the direct network
6029    // it depends on the VCI_RSP FSM
6030
6031    switch (r_vci_rsp_fsm.read() )
6032    {
6033        case RSP_DATA_WRITE : p_vci.rspack = true; break;
6034        case RSP_INS_MISS   : p_vci.rspack = r_vci_rsp_fifo_icache.wok(); break;
6035        case RSP_INS_UNC    : p_vci.rspack = r_vci_rsp_fifo_icache.wok(); break;
6036        case RSP_DATA_MISS  : p_vci.rspack = r_vci_rsp_fifo_dcache.wok(); break;
6037        case RSP_DATA_UNC   : p_vci.rspack = r_vci_rsp_fifo_dcache.wok(); break;
6038        case RSP_DATA_LL    : p_vci.rspack = r_vci_rsp_fifo_dcache.wok(); break;
6039        case RSP_IDLE       : p_vci.rspack = false; break;
6040    } // end switch r_vci_rsp_fsm
6041
6042   
6043    // Send coherence packets on DSPIN P2M
6044    // it depends on the CC_SEND FSM
6045
6046    uint64_t dspin_send_data = 0;
6047    switch ( r_cc_send_fsm.read() )
6048    {
6049        //////////////////
6050        case CC_SEND_IDLE:
6051        {
6052            p_dspin_p2m.write = false;
6053            break;
6054        }
6055        ///////////////////////
6056        case CC_SEND_CLEANUP_1:
6057        {
6058            // initialize dspin send data
6059//            DspinDhccpParam::dspin_set(dspin_send_data,
6060//                                       0,
6061//                                       DspinDhccpParam::P2M_EOP);
6062            DspinDhccpParam::dspin_set(dspin_send_data,
6063                                       m_cc_global_id,
6064                                       DspinDhccpParam::CLEANUP_SRCID);
6065            DspinDhccpParam::dspin_set(dspin_send_data,
6066                                       0,
6067                                       DspinDhccpParam::P2M_BC);
6068
6069            if(r_cc_send_last_client.read() == 0) // dcache active request
6070            {
6071                uint64_t dest = (uint64_t) r_dcache_cc_send_nline.read() 
6072                                >> (m_nline_width - m_x_width - m_y_width) 
6073                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
6074 
6075                DspinDhccpParam::dspin_set(dspin_send_data,
6076                                           dest,
6077                                           DspinDhccpParam::CLEANUP_DEST);
6078
6079                DspinDhccpParam::dspin_set(dspin_send_data,
6080                                           (r_dcache_cc_send_nline.read() & 0x300000000ULL)>>32,
6081                                           DspinDhccpParam::CLEANUP_NLINE_MSB);
6082
6083                DspinDhccpParam::dspin_set(dspin_send_data,
6084                                           r_dcache_cc_send_way.read(),
6085                                           DspinDhccpParam::CLEANUP_WAY_INDEX);
6086
6087                DspinDhccpParam::dspin_set(dspin_send_data,
6088                                           DspinDhccpParam::TYPE_CLEANUP_DATA,
6089                                           DspinDhccpParam::P2M_TYPE);
6090            }
6091            else                                // icache active request
6092            {
6093                uint64_t dest = (uint64_t) r_icache_cc_send_nline.read() 
6094                                >> (m_nline_width - m_x_width - m_y_width) 
6095                                << (DspinDhccpParam::GLOBALID_WIDTH - m_x_width - m_y_width);
6096
6097                DspinDhccpParam::dspin_set(dspin_send_data,
6098                                           dest,
6099                                           DspinDhccpParam::CLEANUP_DEST);
6100
6101                DspinDhccpParam::dspin_set(dspin_send_data,
6102                                           (r_icache_cc_send_nline.read() & 0x300000000ULL)>>32,
6103                                           DspinDhccpParam::CLEANUP_NLINE_MSB);
6104
6105                DspinDhccpParam::dspin_set(dspin_send_data,
6106                                           r_icache_cc_send_way.read(),
6107                                           DspinDhccpParam::CLEANUP_WAY_INDEX);
6108
6109                DspinDhccpParam::dspin_set(dspin_send_data,
6110                                           DspinDhccpParam::TYPE_CLEANUP_INST,
6111                                           DspinDhccpParam::P2M_TYPE);
6112            }
6113            // send flit
6114            p_dspin_p2m.data  = dspin_send_data;
6115            p_dspin_p2m.write = true;
6116            p_dspin_p2m.eop   = false;
6117            break;
6118        }
6119        ///////////////////////
6120        case CC_SEND_CLEANUP_2:
6121        {
6122            // initialize dspin send data
6123//            DspinDhccpParam::dspin_set(dspin_send_data,
6124//                                       1,
6125//                                       DspinDhccpParam::P2M_EOP);
6126
6127            if(r_cc_send_last_client.read() == 0) // dcache active request
6128            {
6129                DspinDhccpParam::dspin_set(dspin_send_data,
6130                                           r_dcache_cc_send_nline.read() & 0xFFFFFFFFULL,
6131                                           DspinDhccpParam::CLEANUP_NLINE_LSB);
6132            }
6133            else                                  // icache active request
6134            {
6135                DspinDhccpParam::dspin_set(dspin_send_data,
6136                                           r_icache_cc_send_nline.read() & 0xFFFFFFFFULL,
6137                                           DspinDhccpParam::CLEANUP_NLINE_LSB);
6138            }
6139            // send flit
6140            p_dspin_p2m.data  = dspin_send_data;
6141            p_dspin_p2m.write = true;
6142            p_dspin_p2m.eop   = true;
6143            break;
6144        }
6145        ///////////////////////
6146        case CC_SEND_MULTI_ACK:
6147        {
6148            // initialize dspin send data
6149//            DspinDhccpParam::dspin_set(dspin_send_data,
6150//                                       1,
6151//                                       DspinDhccpParam::P2M_EOP);
6152            DspinDhccpParam::dspin_set(dspin_send_data,
6153                                       0,
6154                                       DspinDhccpParam::P2M_BC);
6155            DspinDhccpParam::dspin_set(dspin_send_data,
6156                                       DspinDhccpParam::TYPE_MULTI_ACK,
6157                                       DspinDhccpParam::P2M_TYPE);
6158
6159            if(r_cc_send_last_client.read() == 0) // dcache active request
6160            {
6161