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

Last change on this file since 668 was 668, checked in by porquet, 10 years ago

cc_vcache v5: add support for XTN::DEBUG_MASK

Differentiate three types of debugging: icache, dcache and cmd. Make it
possible to set up the mask, via a XTN command (e.g. by the GDB server).

See the wikipage on GDB server for more information ("monitor
cachedebug" section).

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