source: branches/v5/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp @ 296

Last change on this file since 296 was 296, checked in by alain, 11 years ago

introducing major modifications in vci_cc_vcache_wrappers

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