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

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

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

vci_cc_vcache_wrapper:

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

vci_mem_cache

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

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