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

Last change on this file since 616 was 616, checked in by haoliu, 9 years ago

Modification in vci_cc_vcache_wrapper:
a) Non cacheable write request will not any more be sent by multi_write_buffer.

A write non cacheable access is retreated with a synchronous way, like the
read non cacheable access. When Cache L1 receives a write non cacheable request,
it will block the processor until the response of this request arrives.
The advantage of this method is that the cache L1 can supply the virtual address
to OS when it receives a bus error response.

b) In VCI_CMD_STATE, the unc_read request will not check the multi_write_buffer for

an matching address. But the CAS and SC request must be check this point
before sent to the target.

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