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

Last change on this file since 721 was 721, checked in by cfuguet, 10 years ago

vci_cc_vcache_wrapper:

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