source: trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp @ 118

Last change on this file since 118 was 114, checked in by alain, 14 years ago

Improving the print_trace() display.

  • Property svn:eol-style set to native
  • Property svn:keywords set to "Author Date Id Rev URL Revision"
  • Property svn:mime-type set to text/plain
File size: 91.4 KB
Line 
1/* -*- c++ -*-
2 *
3 * SOCLIB_LGPL_HEADER_BEGIN
4 *
5 * This file is part of SoCLib, GNU LGPLv2.1.
6 *
7 * SoCLib is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 of the License.
10 *
11 * SoCLib is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with SoCLib; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * SOCLIB_LGPL_HEADER_END
22 *
23 * Copyright (c) UPMC, Lip6, SoC
24 *         Alain Greiner <alain.greiner@lip6.fr>, 2008
25 *
26 * Maintainers: alain eric.guthmuller@polytechnique.edu nipo
27 */
28
29/////////////////////////////////////////////////////////////////////////////
30// History
31// - 25/04/2008
32//   The existing vci_xcache component has been extended to include
33//   a VCI target port to support a directory based coherence protocol.
34//   Two types of packets can be send by the L2 cache to the L1 cache
35//   * INVALIDATE packets : length = 1
36//   * UPDATE packets : length = n + 2   
37//   The CLEANUP packets are sent by the L1 cache to the L2 cache,
38//   to signal a replaced cache line.
39// - 12/08/2008
40//   The vci_cc_xcache_wrapper component instanciates directly the processsor
41//   iss, in order to supress the processor/cache interface.
42//   According to the VCI advanced specification, this component uses one
43//   word VCI CMD packets for MISS transactions, and accept one word VCI RSP
44//   packets for Write burst  transactions.
45//   The write buffer has been modified to use the WriteBuffer object.
46//   A VCI write burst is constructed when two conditions are satisfied :
47//   The processor make strictly successive write requests, and they are
48//   in the same cache line. The write buffer performs re-ordering, to
49//   respect the contiguous addresses VCI constraint. In case of several
50//   WRITE_WORD requests in the same word, only the last request is conserved.
51//   In case of several WRITE_HALF or WRITE_WORD requests in the same word,
52//   the requests are merged in the same word. In case of uncached write
53//   requests, each request is transmited as a single VCI transaction.
54//   Both the data & instruction caches can be flushed in one single cycle.
55///////////////////////////////////////////////////////////////////////////////
56
57#include <cassert>
58#include "arithmetics.h"
59#include "../include/vci_cc_xcache_wrapper_v4.h"
60
61//#define DEBUG_CC_XCACHE_WRAPPER 1
62
63namespace soclib {
64namespace caba {
65
66    namespace {
67        const char *dcache_fsm_state_str[] = {
68            "DCACHE_IDLE",
69            "DCACHE_WRITE_UPDT",
70            "DCACHE_WRITE_REQ",
71            "DCACHE_MISS_WAIT",
72            "DCACHE_MISS_UPDT",
73            "DCACHE_UNC_WAIT",
74            "DCACHE_SC_WAIT",
75            "DCACHE_INVAL",
76            "DCACHE_ERROR",
77            "DCACHE_CC_CHECK",
78            "DCACHE_CC_INVAL",
79            "DCACHE_CC_UPDT",
80            "DCACHE_CC_CLEANUP",
81        };
82        const char *icache_fsm_state_str[] = {
83            "ICACHE_IDLE",
84            "ICACHE_MISS_WAIT",
85            "ICACHE_MISS_UPDT",
86            "ICACHE_UNC_WAIT",
87            "ICACHE_ERROR",
88            "ICACHE_CC_CLEANUP",
89            "ICACHE_CC_CHECK",
90            "ICACHE_CC_INVAL",
91            "ICACHE_CC_UPDT",
92        };
93        const char *cmd_fsm_state_str[] = {
94            "CMD_IDLE",
95            "CMD_INS_MISS",
96            "CMD_INS_UNC",
97            "CMD_DATA_MISS",
98            "CMD_DATA_UNC",
99            "CMD_DATA_WRITE",
100            "CMD_DATA_SC",
101            "CMD_INS_CLEANUP",
102            "CMD_DATA_CLEANUP",
103        };
104        const char *rsp_fsm_state_str[] = {
105            "RSP_IDLE",
106            "RSP_INS_MISS",
107            "RSP_INS_UNC",
108            "RSP_DATA_MISS",
109            "RSP_DATA_UNC",
110            "RSP_DATA_WRITE",
111            "RSP_DATA_SC",
112            "RSP_INS_CLEANUP",
113            "RSP_DATA_CLEANUP",
114        };
115        const char *tgt_fsm_state_str[] = {
116            "TGT_IDLE",
117            "TGT_UPDT_WORD",
118            "TGT_UPDT_DATA",
119            "TGT_REQ_BROADCAST",
120            "TGT_REQ_ICACHE",
121            "TGT_REQ_DCACHE",
122            "TGT_RSP_BROADCAST",
123            "TGT_RSP_ICACHE",
124            "TGT_RSP_DCACHE",
125        };
126    }
127
128#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXCacheWrapperV4<vci_param, iss_t>
129
130    using soclib::common::uint32_log2;
131
132    /////////////////////////////////
133    tmpl(/**/)::VciCcXCacheWrapperV4(
134    /////////////////////////////////
135            sc_module_name name,
136            int proc_id,
137            const soclib::common::MappingTable &mtp,
138            const soclib::common::MappingTable &mtc,
139            const soclib::common::IntTab &initiator_index_rw,
140            const soclib::common::IntTab &initiator_index_c,
141            const soclib::common::IntTab &target_index,
142            size_t icache_ways,
143            size_t icache_sets,
144            size_t icache_words,
145            size_t dcache_ways,
146            size_t dcache_sets,
147            size_t dcache_words )
148        :
149            soclib::caba::BaseModule(name),
150
151            p_clk("clk"),
152            p_resetn("resetn"),
153            p_vci_ini_rw("vci_ini_rw"),
154            p_vci_ini_c("vci_ini_c"),
155            p_vci_tgt("vci_tgt"),
156
157            m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()),
158            m_segment(mtc.getSegment(target_index)),
159            m_iss(this->name(), proc_id),
160            m_srcid_rw(mtp.indexForId(initiator_index_rw)),
161            m_srcid_c(mtc.indexForId(initiator_index_c)),
162
163            m_dcache_ways(dcache_ways),
164            m_dcache_words(dcache_words),
165            m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
166            m_icache_ways(icache_ways),
167            m_icache_words(icache_words),
168            m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
169
170            r_dcache_fsm("r_dcache_fsm"),
171            r_dcache_fsm_save("r_dcache_fsm_save"),
172            r_dcache_addr_save("r_dcache_addr_save"),
173            r_dcache_wdata_save("r_dcache_wdata_save"),
174            r_dcache_rdata_save("r_dcache_rdata_save"),
175            r_dcache_ll_data("r_dcache_ll_data"),
176            r_dcache_ll_addr("r_dcache_ll_addr"),
177            r_dcache_ll_valid("r_dcache_ll_valid"),
178            r_dcache_type_save("r_dcache_type_save"),
179            r_dcache_be_save("r_dcache_be_save"),
180            r_dcache_cached_save("r_dcache_cached_save"),
181            r_dcache_cleanup_req("r_dcache_cleanup_req"),
182            r_dcache_cleanup_line("r_dcache_cleanup_line"),
183            r_dcache_miss_req("r_dcache_miss_req"),
184            r_dcache_unc_req("r_dcache_unc_req"),
185            r_dcache_write_req("r_dcache_write_req"),
186
187            r_icache_fsm("r_icache_fsm"),
188            r_icache_fsm_save("r_icache_fsm_save"),
189            r_icache_addr_save("r_icache_addr_save"),
190            r_icache_miss_req("r_icache_miss_req"),
191            r_icache_cleanup_req("r_icache_cleanup_req"),
192            r_icache_cleanup_line("r_icache_cleanup_line"),
193
194            r_vci_cmd_fsm("r_vci_cmd_fsm"),
195            r_vci_cmd_min("r_vci_cmd_min"),
196            r_vci_cmd_max("r_vci_cmd_max"),
197            r_vci_cmd_cpt("r_vci_cmd_cpt"),
198
199            r_vci_rsp_fsm("r_vci_rsp_fsm"),
200            r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
201            r_vci_rsp_data_error("r_vci_rsp_data_error"),
202            r_vci_rsp_cpt("r_vci_rsp_cpt"),
203
204            r_icache_buf_unc_valid("r_icache_buf_unc_valid"),
205
206            r_vci_tgt_fsm("r_vci_tgt_fsm"),
207            r_tgt_addr("r_tgt_addr"),
208            r_tgt_word("r_tgt_word"),
209            r_tgt_update("r_tgt_update"),
210            r_tgt_srcid("r_tgt_srcid"),
211            r_tgt_pktid("r_tgt_pktid"),
212            r_tgt_trdid("r_tgt_trdid"),
213            r_tgt_icache_req("r_tgt_icache_req"),
214            r_tgt_dcache_req("r_tgt_dcache_req"),
215
216            r_wbuf("r_wbuf", dcache_words ),
217            r_icache("icache", icache_ways, icache_sets, icache_words),
218            r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
219
220            {
221                r_icache_miss_buf = new data_t[icache_words];
222                r_dcache_miss_buf = new data_t[dcache_words];
223                r_tgt_buf         = new data_t[dcache_words];
224                r_tgt_be          = new be_t[dcache_words];
225
226                SC_METHOD(transition);
227                dont_initialize();
228                sensitive << p_clk.pos();
229
230                SC_METHOD(genMoore);
231                dont_initialize();
232                sensitive << p_clk.neg();
233
234
235                typename iss_t::CacheInfo cache_info;
236                cache_info.has_mmu = false;
237                cache_info.icache_line_size = icache_words*sizeof(data_t);
238                cache_info.icache_assoc = icache_ways;
239                cache_info.icache_n_lines = icache_sets;
240                cache_info.dcache_line_size = dcache_words*sizeof(data_t);
241                cache_info.dcache_assoc = dcache_ways;
242                cache_info.dcache_n_lines = dcache_sets;
243                m_iss.setCacheInfo(cache_info);
244            } // end constructor
245
246    ///////////////////////////////////
247    tmpl(/**/)::~VciCcXCacheWrapperV4()
248    ///////////////////////////////////
249    {
250        delete [] r_icache_miss_buf;
251        delete [] r_dcache_miss_buf;
252        delete [] r_tgt_be;
253        delete [] r_tgt_buf;
254    }
255
256    ////////////////////////
257    tmpl(void)::print_cpi()
258    ////////////////////////
259    {
260        std::cout << "CPU " << m_srcid_rw << " : CPI = "
261            << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
262    }
263    ////////////////////////
264    tmpl(void)::print_stats()
265    ////////////////////////
266    {
267        float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
268        std::cout << "------------------------------------" << std:: dec << std::endl;
269        std::cout << "CPU " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
270        std::cout << "- CPI                = " << (float)m_cpt_total_cycles/run_cycles << std::endl ;
271        std::cout << "- READ RATE          = " << (float)m_cpt_read/run_cycles << std::endl ;
272        std::cout << "- WRITE RATE         = " << (float)m_cpt_write/run_cycles << std::endl;
273        std::cout << "- UNCACHED READ RATE = " << (float)m_cpt_unc_read/m_cpt_read << std::endl ;
274        std::cout << "- CACHED WRITE RATE  = " << (float)m_cpt_write_cached/m_cpt_write << std::endl ;
275        std::cout << "- IMISS_RATE         = " << (float)m_cpt_ins_miss/run_cycles << std::endl;
276        std::cout << "- DMISS RATE         = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl ;
277        std::cout << "- INS MISS COST      = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl;
278        std::cout << "- IMISS TRANSACTION  = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl;
279        std::cout << "- DMISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl;
280        std::cout << "- DMISS TRANSACTION  = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl;
281        std::cout << "- UNC COST           = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl;
282        std::cout << "- UNC TRANSACTION    = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl;
283        std::cout << "- WRITE COST         = " << (float)m_cost_write_frz/m_cpt_write << std::endl;
284        std::cout << "- WRITE TRANSACTION  = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl;
285        std::cout << "- WRITE LENGTH       = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl;
286    }
287    ////////////////////////////////////
288    tmpl(void)::print_trace(size_t mode)
289    ////////////////////////////////////
290    {
291        typename iss_t::InstructionRequest  ireq;
292        typename iss_t::DataRequest         dreq;
293        m_iss.getRequests( ireq, dreq );
294
295        std::cout << std::dec << "CC_XCACHE_WRAPPER " << name() << std::endl;
296        std::cout << " proc state  : PC = " << std::hex << ireq.addr << " / AD = " << dreq.addr
297                  << std::dec << " / V = " << dreq.valid << " / TYPE = " << dreq.type << std::endl;
298        std::cout << " cache state : " << icache_fsm_state_str[r_icache_fsm] << " / "
299                                       << dcache_fsm_state_str[r_dcache_fsm] << " / "
300                                       << cmd_fsm_state_str[r_vci_cmd_fsm] << " / "
301                                       << rsp_fsm_state_str[r_vci_rsp_fsm] << " / "
302                                       << tgt_fsm_state_str[r_vci_tgt_fsm] << std::endl;
303        if( r_vci_tgt_fsm != TGT_IDLE )
304        {
305            std::cout << "    ... coherence request address = " << std::hex << r_tgt_addr.read() << std::endl;
306        }
307        if(mode & 0x1)
308        {
309            r_wbuf.printTrace();
310        }
311    }
312    //////////////////////////
313    tmpl(void)::transition()
314    //////////////////////////
315    {
316        if ( ! p_resetn.read() ) {
317
318            m_iss.reset();
319
320            // FSM states
321            r_dcache_fsm = DCACHE_IDLE;
322            r_icache_fsm = ICACHE_IDLE;
323            r_vci_cmd_fsm = CMD_IDLE;
324            r_vci_rsp_fsm = RSP_IDLE;
325            r_vci_tgt_fsm = TGT_IDLE;
326
327            // write buffer & caches
328            r_wbuf.reset();
329            r_icache.reset();
330            r_dcache.reset();
331
332            // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI  FSMs
333            r_icache_miss_req    = false;
334            r_icache_unc_req     = false;
335            r_icache_cleanup_req = false;
336            r_dcache_miss_req    = false;
337            r_dcache_unc_req     = false;
338            r_dcache_sc_req      = false;
339            r_dcache_write_req   = false;
340            r_dcache_cleanup_req = false;
341
342            // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
343            r_tgt_icache_req     = false;
344            r_tgt_dcache_req     = false;
345
346            // internal messages in DCACHE et ICACHE FSMs
347            r_icache_inval_rsp   = false;
348            r_dcache_inval_rsp   = false;
349
350            // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs
351            r_dcache_ll_valid      = false;
352            r_icache_buf_unc_valid = false;
353            r_vci_rsp_data_error   = false;
354            r_vci_rsp_ins_error    = false;
355
356            // activity counters
357            m_cpt_dcache_data_read  = 0;
358            m_cpt_dcache_data_write = 0;
359            m_cpt_dcache_dir_read  = 0;
360            m_cpt_dcache_dir_write = 0;
361            m_cpt_icache_data_read  = 0;
362            m_cpt_icache_data_write = 0;
363            m_cpt_icache_dir_read  = 0;
364            m_cpt_icache_dir_write = 0;
365
366            m_cpt_cc_update = 0;
367            m_cpt_cc_inval = 0;
368
369            m_cpt_frz_cycles = 0;
370            m_cpt_total_cycles = 0;
371
372            m_cpt_read = 0;
373            m_cpt_write = 0;
374            m_cpt_data_miss = 0;
375            m_cpt_ins_miss = 0;
376            m_cpt_unc_read = 0;
377            m_cpt_write_cached = 0;
378
379            m_cost_write_frz = 0;
380            m_cost_data_miss_frz = 0;
381            m_cost_unc_read_frz = 0;
382            m_cost_ins_miss_frz = 0;
383
384            m_cpt_imiss_transaction = 0;
385            m_cpt_dmiss_transaction = 0;
386            m_cpt_unc_transaction = 0;
387            m_cpt_write_transaction = 0;
388
389            m_cost_imiss_transaction = 0;
390            m_cost_dmiss_transaction = 0;
391            m_cost_unc_transaction = 0;
392            m_cost_write_transaction = 0;
393            m_length_write_transaction = 0;
394
395            return;
396        }
397
398#if DEBUG_CC_XCACHE_WRAPPER
399        std::cout << "--------------------------------------------" << std::endl;
400        std::cout << std::dec << "CC_XCACHE_WRAPPER " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
401        std::cout             << " tgt fsm    = " << tgt_fsm_state_str[r_vci_tgt_fsm] << std::endl
402            << " dcache fsm = " << dcache_fsm_state_str[r_dcache_fsm] << std::endl
403            << " icache fsm = " << icache_fsm_state_str[r_icache_fsm] << std::endl
404            << " cmd fsm    = " << cmd_fsm_state_str[r_vci_cmd_fsm] << std::endl
405            << " rsp fsm    = " << rsp_fsm_state_str[r_vci_rsp_fsm] << std::endl;
406#endif
407
408        m_cpt_total_cycles++;
409
410        /////////////////////////////////////////////////////////////////////
411        // The TGT_FSM controls the following ressources:
412        // - r_vci_tgt_fsm
413        // - r_tgt_buf[nwords]
414        // - r_tgt_be[nwords]
415        // - r_tgt_update
416        // - r_tgt_word
417        // - r_tgt_addr
418        // - r_tgt_srcid
419        // - r_tgt_trdid
420        // - r_tgt_pktid
421        // All VCI commands must be CMD_WRITE.
422        // If the VCI address offset is null, the command is an invalidate
423        // request. It is an update request otherwise.
424        // The VCI_TGT FSM stores the external request arguments in the
425        // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req
426        // & r_tgt_dcache_req flip-flops to signal the external request to
427        // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
428        // of the update or invalidate request in the RSP state.
429        // -  for an invalidate request the VCI packet length is 1 word.
430        // The WDATA field contains the line index (i.e. the Z & Y fields).
431        // -  for an update request the VCI packet length is (n+2) words.
432        // The WDATA field of the first VCI word contains the line number.
433        // The WDATA field of the second VCI word contains the word index.
434        // The WDATA field of the n following words contains the values.
435        // -  for both invalidate & update requests, the VCI response
436        // is one single word.
437        // In case of errors in the VCI command packet, the simulation
438        // is stopped with an error message.
439        /////////////////////////////////////////////////////////////////////
440
441        switch(r_vci_tgt_fsm) {
442
443            case TGT_IDLE:
444                if ( p_vci_tgt.cmdval.read() )
445                {
446                    addr_40 address = p_vci_tgt.address.read();
447
448                    if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE)
449                    {
450                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
451                        std::cout << "coherence request is not a write" << std::endl;
452                        std::cout << "oddress = " << std::hex << address << std::endl;
453                        std::cout << "srcid   = " << std::hex << p_vci_tgt.srcid.read() << std::endl;
454                        exit(0);
455                    }
456
457                    // multi-update or multi-invalidate for data type
458                    if ( ((address&0x3) != 0x3) && (! m_segment.contains(address)) )
459                    {
460                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
461                        std::cout << "out of segment coherence request" << std::endl;
462                        std::cout << "oddress = " << std::hex << address << std::endl;
463                        std::cout << "srcid   = " << std::hex << p_vci_tgt.srcid.read() << std::endl;
464                        exit(0);
465                    }
466
467                    r_tgt_addr = (((addr_40) ((p_vci_tgt.be.read() & 0x3) << 32)) |
468                                 ((addr_40) (p_vci_tgt.wdata.read()))) * m_dcache_words * 4;     
469                    r_tgt_srcid = p_vci_tgt.srcid.read();
470                    r_tgt_trdid = p_vci_tgt.trdid.read();
471                    r_tgt_pktid = p_vci_tgt.pktid.read();
472                    r_tgt_plen  = p_vci_tgt.plen.read();
473                   
474                    if ( (address&0x3) == 0x3 )   // broadcast invalidate for data or instruction type
475                    {
476                        if ( ! p_vci_tgt.eop.read() )
477                        {
478                            std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
479                            std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
480                            exit(0);
481                        }
482                        r_tgt_update = false;
483                        r_tgt_brdcast= true;
484                        r_vci_tgt_fsm = TGT_REQ_BROADCAST;
485                        m_cpt_cc_inval++ ;
486                    }
487                    else                    // multi-update or multi-invalidate for data type
488                    {
489                        uint32_t cell = address - m_segment.baseAddress(); // addr_40
490                        r_tgt_brdcast = false;
491                        if (cell == 0)
492                        {                                       // invalidate data
493                            if ( ! p_vci_tgt.eop.read() )
494                            {
495                                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
496                                std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
497                                exit(0);
498                            }
499                            r_tgt_update = false;
500                            r_vci_tgt_fsm = TGT_REQ_DCACHE;
501                            m_cpt_cc_inval++ ;
502                        }
503                        else if (cell == 4)                     // invalidate instruction
504                        {                         
505                            if ( ! p_vci_tgt.eop.read() )
506                            {
507                                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
508                                std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
509                                exit(0);
510                            }
511                            r_tgt_update = false;
512                            r_vci_tgt_fsm = TGT_REQ_ICACHE;
513                            m_cpt_cc_inval++ ;
514                        }
515                        else if ( (cell == 8) || (cell==12) )    // update data or instruction
516                        {                               
517                            if ( p_vci_tgt.eop.read() )
518                            {
519                                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
520                                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
521                                exit(0);
522                            }
523                            if(cell == 8)
524                                r_tgt_update_data = true;
525                            else
526                                r_tgt_update_data = false;
527                            r_tgt_update = true;
528                            r_vci_tgt_fsm = TGT_UPDT_WORD;
529                            m_cpt_cc_update++ ;
530                        }
531
532                    } // end if address
533                } // end if cmdval
534                break;
535
536            case TGT_UPDT_WORD:
537                if (p_vci_tgt.cmdval.read())
538                {
539                    if ( p_vci_tgt.eop.read() )
540                    {
541                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
542                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
543                        exit(0);
544                    }
545                    for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_be[i] = 0;
546                    r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
547#ifdef COHERENCE_DEBUG
548                    std::cout << "PROC " << m_srcid_rw << " update, line : " << std::hex << r_tgt_addr.read() << " word : " << p_vci_tgt.wdata.read() << std::dec << std::endl;
549#endif
550                    r_vci_tgt_fsm = TGT_UPDT_DATA;
551                }
552                break;
553
554            case TGT_UPDT_DATA:
555                if (p_vci_tgt.cmdval.read())
556                {
557                    size_t word = r_tgt_word.read();
558                    if ( word >= m_dcache_words )
559                    {
560                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
561                        std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
562                        exit(0);
563                    }
564#ifdef COHERENCE_DEBUG
565                    std::cout << "PROC " << m_srcid_rw << " update, data : " << p_vci_tgt.wdata.read() << " be : " << std::hex << p_vci_tgt.be.read() << std::dec << std::endl;
566#endif
567                    r_tgt_buf[word] = p_vci_tgt.wdata.read();
568                    r_tgt_be[word] = p_vci_tgt.be.read();
569                    r_tgt_word = word + 1;
570                    if (p_vci_tgt.eop.read()){
571                      if(r_tgt_update_data.read()){
572                        r_vci_tgt_fsm = TGT_REQ_DCACHE;
573                      } else {
574                        r_vci_tgt_fsm = TGT_REQ_ICACHE;
575                      }
576                    }
577                }
578                break;
579
580            case TGT_REQ_BROADCAST:
581                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
582                {
583                    r_vci_tgt_fsm = TGT_RSP_BROADCAST;
584                    r_tgt_icache_req = true;
585                    r_tgt_dcache_req = true;
586                }
587                break;
588                ////////////////////
589            case TGT_REQ_ICACHE:
590                {
591                    if ( !r_tgt_icache_req.read() )
592                    {
593                        r_vci_tgt_fsm = TGT_RSP_ICACHE;
594                        r_tgt_icache_req = true;
595                    }
596                    break;
597                }
598
599            case TGT_REQ_DCACHE:
600                if ( !r_tgt_dcache_req.read() )
601                {
602                    r_vci_tgt_fsm = TGT_RSP_DCACHE;
603                    r_tgt_dcache_req = true;
604                }
605                break;
606
607            case TGT_RSP_BROADCAST:
608                if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
609                {
610                    // one response
611                    if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
612                    {
613                        if ( p_vci_tgt.rspack.read() )
614                        {
615                            r_vci_tgt_fsm = TGT_IDLE;
616                            r_tgt_icache_rsp = false;
617                            r_tgt_dcache_rsp = false;
618                        }
619                    }
620
621                    // if data and instruction have the inval line, need two responses 
622                    if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
623                    {
624                        if ( p_vci_tgt.rspack.read() )
625                        {
626                            r_tgt_icache_rsp = false; // only reset one for respond the second time
627                        }
628                    }
629
630                    // if there is no need for a response
631                    if ( !r_tgt_icache_rsp && !r_tgt_dcache_rsp )
632                    {
633                        r_vci_tgt_fsm = TGT_IDLE;
634                    }
635
636                }
637                break;
638                ////////////////////
639            case TGT_RSP_ICACHE:
640                {
641                    if ( (p_vci_tgt.rspack.read() || !r_tgt_icache_rsp.read()) && !r_tgt_icache_req.read() )
642                    {
643                        r_vci_tgt_fsm = TGT_IDLE;
644                        r_tgt_icache_rsp = false;
645                    }
646                    break;
647                }
648
649            case TGT_RSP_DCACHE:
650                {
651                    if ( (p_vci_tgt.rspack.read() || !r_tgt_dcache_rsp.read()) && !r_tgt_dcache_req.read() )
652                    {
653                        r_vci_tgt_fsm = TGT_IDLE;
654                        r_tgt_dcache_rsp = false;
655                    }
656                    break;
657                }
658        } // end switch TGT_FSM
659
660        /////////////////////////////////////////////////////////////////////
661        // The ICACHE FSM controls the following ressources:
662        // - r_icache_fsm
663        // - r_icache_fsm_save
664        // - r_icache instruction cache access
665        // - r_icache_addr_save
666        // - r_icache_miss_req set
667        // - r_icache_unc_req set
668        // - r_icache_buf_unc_valid set
669        // - r_vci_rsp_ins_error reset
670        // - r_tgt_icache_req reset
671        // - ireq & irsp structures for communication with the processor
672        //
673        // 1/ External requests (update or invalidate) have highest priority.
674        //    They are taken into account in the IDLE and WAIT states.
675        //    As external hit should be extremly rare on the ICACHE,
676        //    all external requests are handled as invalidate...
677        //    In case of external request the ICACHE FSM goes to the CC_CHECK
678        //    state to test the external hit, and returns in the
679        //    pre-empted state after completion.
680        // 2/ Processor requests are taken into account only in the IDLE state.
681        //    In case of MISS, or in case of uncached instruction, the FSM
682        //    writes the missing address line in the  r_icache_addr_save register
683        //    and sets the r_icache_miss_req or the r_icache_unc_req flip-flops.
684        //    These request flip-flops are reset by the VCI_RSP FSM
685        //    when the VCI transaction is completed and the r_icache_buf_unc_valid
686        //    is set in case of uncached access.
687        //    In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
688        //    flip-flop. It is reset by the ICACHE FSM.
689        ///////////////////////////////////////////////////////////////////////
690
691        typename iss_t::InstructionRequest  ireq = ISS_IREQ_INITIALIZER;
692        typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
693
694        typename iss_t::DataRequest  dreq = ISS_DREQ_INITIALIZER;
695        typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
696
697        m_iss.getRequests( ireq, dreq );
698
699#if DEBUG_CC_XCACHE_WRAPPER
700        std::cout << " Instruction Request: " << ireq << std::endl;
701#endif
702
703        switch(r_icache_fsm) {
704            /////////////////
705            case ICACHE_IDLE:
706                {
707                    if ( r_tgt_icache_req ) {   // external request
708                        if ( ireq.valid ) m_cost_ins_miss_frz++;
709                        r_icache_fsm = ICACHE_CC_CHECK;
710                        r_icache_fsm_save = r_icache_fsm.read();
711                        break;
712                    }
713                    if ( ireq.valid ) {
714                        data_t  icache_ins = 0;
715                        bool    icache_hit = false;
716                        bool    icache_cached = m_cacheability_table[(vci_addr_t)ireq.addr];
717                        // icache_hit & icache_ins evaluation
718                        if ( icache_cached ) {
719                            icache_hit = r_icache.read((vci_addr_t) ireq.addr, &icache_ins);
720                        } else {
721                            icache_hit = ( r_icache_buf_unc_valid && ((addr_40) ireq.addr == (addr_40)r_icache_addr_save) );
722                            icache_ins = r_icache_miss_buf[0];
723                        }
724                        if ( ! icache_hit ) {
725                            m_cpt_ins_miss++;
726                            m_cost_ins_miss_frz++;
727                            r_icache_addr_save = (addr_40) ireq.addr;
728                            if ( icache_cached ) {
729                                r_icache_fsm = ICACHE_MISS_WAIT;
730                                r_icache_miss_req = true;
731                            } else {
732                                r_icache_fsm = ICACHE_UNC_WAIT;
733                                r_icache_unc_req = true;
734                            }
735                        } else {
736                            r_icache_buf_unc_valid = false;
737                        }
738                        m_cpt_icache_dir_read += m_icache_ways;
739                        m_cpt_icache_data_read += m_icache_ways;
740                        irsp.valid          = icache_hit;
741                        irsp.instruction    = icache_ins;
742                    }
743                    break;
744                }
745                //////////////////////
746            case ICACHE_MISS_WAIT:
747                {
748                    m_cost_ins_miss_frz++;
749                    if ( r_tgt_icache_req ) {   // external request
750                        r_icache_fsm = ICACHE_CC_CHECK;
751                        r_icache_fsm_save = r_icache_fsm.read();
752                        break;
753                    }
754                    if ( !r_icache_miss_req && !r_icache_inval_rsp ) { // Miss read response and no invalidation
755                        if ( r_vci_rsp_ins_error ) {
756                            r_icache_fsm = ICACHE_ERROR;
757                        } else {
758                            r_icache_fsm = ICACHE_MISS_UPDT;
759                        }
760                    }
761                    if ( !r_icache_miss_req && r_icache_inval_rsp ) { // Miss read response and invalidation
762                        if ( r_vci_rsp_ins_error ) {
763                            r_icache_inval_rsp = false;
764                            r_icache_fsm = ICACHE_ERROR;
765                        } else {
766                            r_icache_inval_rsp = false;
767                            r_icache_fsm = ICACHE_CC_CLEANUP;
768                        }
769                    }
770                    break;
771                }
772                /////////////////////
773            case ICACHE_UNC_WAIT:
774                {
775                    m_cost_ins_miss_frz++;
776                    if ( r_tgt_icache_req ) {   // external request
777                        r_icache_fsm = ICACHE_CC_CHECK;
778                        r_icache_fsm_save = r_icache_fsm.read();
779                        break;
780                    }
781                    if ( !r_icache_unc_req ) {
782                        if ( r_vci_rsp_ins_error ) {
783                            r_icache_fsm = ICACHE_ERROR;
784                        } else {
785                            r_icache_fsm = ICACHE_IDLE;
786                            r_icache_buf_unc_valid = true;
787                        }
788                    }
789                    break;
790                }
791                //////////////////
792            case ICACHE_ERROR:
793                {
794                    if ( (addr_40)ireq.addr == (addr_40)r_icache_addr_save ) {
795                        irsp.error          = true;
796                        irsp.valid          = true;
797                    }
798                    r_icache_fsm = ICACHE_IDLE;
799                    r_vci_rsp_ins_error = false;
800                    break;
801                }
802                //////////////////////
803            case ICACHE_MISS_UPDT:
804                {
805                    if ( r_tgt_icache_req ) {   // external request
806                        r_icache_fsm = ICACHE_CC_CHECK;
807                        r_icache_fsm_save = r_icache_fsm.read();
808                        break;
809                    }
810                    if(!r_icache_cleanup_req.read() && !r_icache_inval_rsp){
811                        vci_addr_t ad   = 0;
812                        ad              = (vci_addr_t) r_icache_addr_save.read();
813                        data_t*   buf   = r_icache_miss_buf;
814                        vci_addr_t victim_index = 0;
815                        m_cpt_icache_dir_write++;
816                        m_cpt_icache_data_write++;
817                        if ( ireq.valid ) m_cost_ins_miss_frz++;
818
819                        r_icache_cleanup_req  = r_icache.update(ad, buf, &victim_index);
820                        r_icache_cleanup_line = (addr_40) victim_index;
821
822                        r_icache_fsm        = ICACHE_IDLE;
823                        break;
824                    }
825                    if(r_icache_inval_rsp){
826                        if ( ireq.valid ) m_cost_ins_miss_frz++;
827                        r_icache_inval_rsp  = false;
828                        r_icache_fsm = ICACHE_CC_CLEANUP;
829                        break;
830                    }
831                    if ( ireq.valid ) m_cost_ins_miss_frz++;
832                }
833                ////////////////////
834            case ICACHE_CC_CLEANUP:
835                {
836                    // external cache invalidate request
837                    if ( r_tgt_icache_req )     
838                    {
839                        r_icache_fsm = ICACHE_CC_CHECK;
840                        r_icache_fsm_save = r_icache_fsm.read();
841                        break;
842                    }
843                    // cleanup
844                    if(!r_icache_cleanup_req){
845                        r_icache_cleanup_req = true;
846                        r_icache_cleanup_line = r_icache_addr_save.read() >> (uint32_log2(m_icache_words) + 2);   
847                        r_icache_fsm = ICACHE_IDLE;
848                    }
849                    break;
850                }
851                /////////////////////
852            case ICACHE_CC_CHECK:   // read directory in case of invalidate or update request
853                {
854
855                    m_cpt_icache_dir_read += m_icache_ways;
856                    m_cpt_icache_data_read += m_icache_ways;
857                    addr_40  ad           = r_tgt_addr;
858                    data_t  icache_rdata = 0;
859
860                    if(( ( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT ) ) &&
861                            ( (r_icache_addr_save.read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) {
862                        r_icache_inval_rsp = true;
863                        r_tgt_icache_req = false;
864                        if(r_tgt_update){    // Also send a cleanup and answer
865                            r_tgt_icache_rsp     = true;
866                        } else {            // Also send a cleanup but don't answer
867                            r_tgt_icache_rsp     = false;
868                        }
869                        r_icache_fsm = r_icache_fsm_save;
870                    } else {
871                        bool    icache_hit   = r_icache.read(ad, &icache_rdata);
872                        if ( icache_hit && r_tgt_update ) {
873                            r_icache_fsm = ICACHE_CC_UPDT;
874                            // complete the line buffer in case of update
875                            for(size_t i=0; i<m_icache_words; i++){
876                                data_t rdata = 0;
877                                r_icache.read(ad + i*4,&rdata);
878                                data_t mask = vci_param::be2mask(r_tgt_be[i]);
879                                r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata);
880                            }
881                        } else if ( icache_hit && !r_tgt_update ) {
882                            r_icache_fsm = ICACHE_CC_INVAL;
883                        } else { // instruction not found (can happen)
884                            r_tgt_icache_req = false;
885                            if(r_tgt_update){
886                                r_tgt_icache_rsp = true;
887                            } else {
888                                r_tgt_icache_rsp = false;
889                            }
890                            r_icache_fsm = r_icache_fsm_save;
891                        }
892                    }
893                    break;
894                }
895                /////////////////////
896            case ICACHE_CC_INVAL: 
897                {                       
898                    addr_40    ad  = r_tgt_addr;
899                    if ( ireq.valid ) m_cost_ins_miss_frz++;
900                    m_cpt_icache_dir_read += m_icache_ways;
901                    r_tgt_icache_rsp = true;
902                    r_icache.inval(ad);
903                    r_tgt_icache_req = false;
904                    r_icache_fsm = r_icache_fsm_save;
905                    break;
906                }   
907                /////////////////////
908            case ICACHE_CC_UPDT:
909                {                       
910                    m_cpt_icache_dir_write++;
911                    m_cpt_icache_data_write++;
912                    addr_40    ad  = r_tgt_addr.read();
913                    data_t* buf    = r_tgt_buf;
914                    for(size_t i=0; i<m_icache_words;i++){
915                        if(r_tgt_be[i]) r_icache.write( ad + i*4, buf[i]);
916                    }
917                    r_tgt_icache_req = false;
918                    r_tgt_icache_rsp = true;
919                    r_icache_fsm     = r_icache_fsm_save.read();
920                    break;
921                }   
922
923        } // end switch r_icache_fsm
924
925#if DEBUG_CC_XCACHE_WRAPPER
926        std::cout << " Instruction Response: " << irsp << std::endl;
927#endif
928
929        //////////////////////////////////////////////////////////////////////://///////////
930        // The DCACHE FSM controls the following ressources:
931        // - r_dcache_fsm
932        // - r_dcache_fsm_save
933        // - r_dcache (data cache access)
934        // - r_dcache_addr_save
935        // - r_dcache_wdata_save
936        // - r_dcache_rdata_save
937        // - r_dcache_type_save
938        // - r_dcache_be_save
939        // - r_dcache_cached_save
940        // - r_dcache_miss_req set
941        // - r_dcache_unc_req set
942        // - r_dcache_write_req set
943        // - r_dcache_cleanup_req set
944        // - r_vci_rsp_data_error reset
945        // - r_tgt_dcache_req reset
946        // - r_wbuf write
947        // - dreq & drsp structures for communication with the processor
948        //
949        // 1/ EXTERNAL REQUEST :
950        //    There is an external request when the tgt_dcache req flip-flop is set,
951        //    requesting a line invalidation or a line update.
952        //    External requests are taken into account in the states  IDLE, WRITE_REQ, 
953        //    UNC_WAIT, MISS_WAIT, and have the highest priority :
954        //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
955        //    goes to the CC_CHECK state to execute the requested action, and returns to the
956        //    pre-empted state.
957        //  2/ PROCESSOR REQUEST :
958        //   In order to support VCI write burst, the processor requests are taken into account
959        //   in the WRITE_REQ state as well as in the IDLE state.
960        //   - In the IDLE state, the processor request cannot be satisfied if
961        //   there is a cached read miss, or an uncached read.
962        //   - In the WRITE_REQ state, the request cannot be satisfied if
963        //   there is a cached read miss, or an uncached read,
964        //   or when the write buffer is full.
965        //   - In all other states, the processor request is not satisfied.
966        //
967        //   The cache access takes into account the cacheability_table.
968        //   In case of processor request, there is five conditions to exit the IDLE state:
969        //   - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal),
970        //     then to the MISS_UPDT state, and finally to the IDLE state.
971        //   - UNCACHED READ  => to the UNC_WAIT state (waiting the r_miss_ok signal),
972        //     and to the IDLE state.
973        //   - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state.
974        //   - WRITE MISS => directly to the WRITE_REQ state to access the write buffer.
975        //   - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state.
976        //
977        // Error handling :  Read Bus Errors are synchronous events, but
978        // Write Bus Errors are asynchronous events (processor is not frozen).
979        // - If a Read Bus Error is detected, the VCI_RSP FSM sets the
980        //   r_vci_rsp_data_error flip-flop, and the synchronous error is signaled
981        //   by the DCACHE FSM.
982        // - If a Write Bus Error is detected, the VCI_RSP FSM  signals
983        //   the asynchronous error using the setWriteBerr() method.
984        ///////////////////////////////////////////////////////////////////////////////////
985
986#if DEBUG_CC_XCACHE_WRAPPER
987        std::cout << " Data Request: " << dreq << std::endl;
988#endif
989
990        //if( (m_cpt_total_cycles % 10000) ==0 ) std::cout << std::dec << "Proc " << m_srcid << " Data Request: " << dreq << std::endl;
991
992        switch ( r_dcache_fsm ) {
993
994            /////////////////////
995            case DCACHE_WRITE_REQ:
996                {
997                    if ( r_tgt_dcache_req ) {   // external request
998                        r_dcache_fsm = DCACHE_CC_CHECK;
999                        r_dcache_fsm_save = r_dcache_fsm;
1000                        break;
1001                    }
1002                    // try to post the write request in the write buffer
1003                    if ( !r_dcache_write_req ) {    // no previous write transaction     
1004                        if ( r_wbuf.wok(r_dcache_addr_save) ) {   // write request in the same cache line
1005                            r_wbuf.write(r_dcache_addr_save, r_dcache_be_save, r_dcache_wdata_save);
1006                            // close the write packet if uncached
1007                            if ( !r_dcache_cached_save ){
1008                                r_dcache_write_req = true ;
1009                            }
1010                        } else {   
1011                            // close the write packet if write request not in the same cache line
1012                            r_dcache_write_req = true; 
1013                            if(!m_srcid_rw) {
1014                            }
1015                            m_cost_write_frz++;
1016                            break;  // posting request not possible : stay in DCACHE_WRITEREQ state
1017                        }
1018                    } else {    //  previous write transaction not completed
1019                        m_cost_write_frz++;
1020                        break;  // posting request not possible : stay in DCACHE_WRITEREQ state 
1021                    }
1022
1023                    // close the write packet if the next processor request is not a write
1024                    if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE) ) {
1025                        r_dcache_write_req = true ;
1026                    }
1027
1028                    // The next state and the processor request parameters are computed
1029                    // as in the DCACHE_IDLE state (see below ...)
1030                }
1031                /////////////////
1032            case DCACHE_IDLE:
1033                {
1034                    if ( r_tgt_dcache_req ) {   // external request
1035                        r_dcache_fsm = DCACHE_CC_CHECK;
1036                        r_dcache_fsm_save = r_dcache_fsm;
1037                        break;
1038                    }
1039
1040                    if ( dreq.valid ) {             
1041                        bool        dcache_hit     = false;
1042                        data_t      dcache_rdata   = 0;
1043                        bool        dcache_cached;
1044                        m_cpt_dcache_data_read += m_dcache_ways;
1045                        m_cpt_dcache_dir_read += m_dcache_ways;
1046
1047                        // dcache_cached evaluation
1048                        switch (dreq.type) {
1049                            case iss_t::DATA_SC:
1050                            case iss_t::XTN_READ:
1051                            case iss_t::XTN_WRITE:
1052                                dcache_cached = false;
1053                                break;
1054                            default:
1055                                dcache_cached = m_cacheability_table[(vci_addr_t)dreq.addr];
1056                        }
1057
1058                        // dcache_hit & dcache_rdata evaluation
1059                        if ( dcache_cached ) {
1060                            dcache_hit = r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
1061                        } else {
1062                            dcache_hit = false;
1063                        }
1064
1065                        switch( dreq.type ) {
1066                            case iss_t::DATA_READ:
1067                            case iss_t::DATA_LL:
1068                                m_cpt_read++;
1069                                if ( dcache_hit ) {
1070                                    r_dcache_fsm = DCACHE_IDLE;
1071                                    drsp.valid = true;
1072                                    drsp.rdata = dcache_rdata;
1073                                    if(dreq.type == iss_t::DATA_LL){
1074                                        r_dcache_ll_valid = true;
1075                                        r_dcache_ll_data = dcache_rdata;
1076                                        r_dcache_ll_addr = (vci_addr_t) dreq.addr;
1077#ifdef COHERENCE_DEBUG
1078                                        std::cout << "Value returned for LL at address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
1079                                        r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
1080                                        std::cout << "Value stored at this  address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
1081#endif
1082                                    }
1083                                } else {
1084                                    if ( dcache_cached ) {
1085                                        m_cpt_data_miss++;
1086                                        m_cost_data_miss_frz++;
1087                                        r_dcache_miss_req = true;
1088                                        r_dcache_fsm = DCACHE_MISS_WAIT;
1089                                    } else {
1090                                        m_cpt_unc_read++;
1091                                        m_cost_unc_read_frz++;
1092                                        r_dcache_unc_req = true;
1093                                        r_dcache_fsm = DCACHE_UNC_WAIT;
1094                                    }
1095                                }
1096                                break;
1097                            case iss_t::DATA_SC:
1098                            {
1099                                m_cpt_unc_read++;
1100                                m_cost_unc_read_frz++;
1101                                if(r_dcache_ll_valid.read() && (r_dcache_ll_addr.read() == (vci_addr_t)dreq.addr)){
1102                                    r_dcache_sc_req = true;
1103                                    r_dcache_fsm = DCACHE_SC_WAIT;
1104                                } else {
1105                                    drsp.valid = true;
1106                                    drsp.rdata = 1; // SC rsp NOK
1107                                    r_dcache_ll_valid = false;
1108                                }
1109                                break;
1110                            }
1111                            case iss_t::XTN_READ:
1112                            case iss_t::XTN_WRITE:
1113                                    // only DCACHE INVALIDATE request are supported
1114                                    if ( dreq.addr/4 == iss_t::XTN_DCACHE_INVAL ){
1115                                        r_dcache_fsm = DCACHE_INVAL;
1116                                    } else {
1117                                        r_dcache_fsm = DCACHE_IDLE;
1118                                    }
1119                                    drsp.valid = true;
1120                                    drsp.rdata = 0;
1121                                    break;
1122                            case iss_t::DATA_WRITE:
1123                                    m_cpt_write++;
1124                                    if ( dcache_hit && dcache_cached ) {
1125                                        r_dcache_fsm = DCACHE_WRITE_UPDT;
1126                                        m_cpt_write_cached++;
1127                                    } else {
1128                                        r_dcache_fsm = DCACHE_WRITE_REQ;
1129                                    }
1130                                    drsp.valid = true;
1131                                    drsp.rdata = 0;
1132                                    break;
1133                        } // end switch dreq.type
1134
1135                        r_dcache_addr_save      = (addr_40) dreq.addr;
1136                        r_dcache_type_save      = dreq.type;
1137                        r_dcache_wdata_save     = dreq.wdata;
1138                        r_dcache_be_save        = dreq.be;
1139                        r_dcache_rdata_save     = dcache_rdata;
1140                        r_dcache_cached_save    = dcache_cached;
1141
1142                    } else {    // end if dreq.valid
1143                        r_dcache_fsm = DCACHE_IDLE;
1144                    }
1145                    // processor request are not accepted in the WRITE_REQUEST state
1146                    // when the write buffer is not writeable
1147                    if ( (r_dcache_fsm == DCACHE_WRITE_REQ) &&
1148                            (r_dcache_write_req || !r_wbuf.wok(r_dcache_addr_save)) ) {
1149                        drsp.valid = false;
1150                        drsp.rdata = 0;
1151                    }
1152                    break;
1153                }
1154                ///////////////////////
1155            case DCACHE_WRITE_UPDT:
1156                {
1157                    m_cpt_dcache_data_write++;
1158                    data_t mask = vci_param::be2mask(r_dcache_be_save);
1159                    data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
1160                    vci_addr_t ad = r_dcache_addr_save.read();
1161                    r_dcache.write(ad, wdata);
1162                    r_dcache_fsm = DCACHE_WRITE_REQ;
1163                    break;
1164                }
1165                //////////////////////
1166            case DCACHE_MISS_WAIT:
1167                {
1168
1169                    if ( dreq.valid ) m_cost_data_miss_frz++;
1170                    if ( r_tgt_dcache_req.read() ) {   // external request
1171                        r_dcache_fsm = DCACHE_CC_CHECK;
1172                        r_dcache_fsm_save = r_dcache_fsm;
1173                        break;
1174                    }
1175                    if ( !r_dcache_miss_req && !r_dcache_inval_rsp ) { // Miss read response and no invalidation
1176                        if ( r_vci_rsp_data_error ) {
1177                            r_dcache_fsm = DCACHE_ERROR;
1178                        } else {
1179                            r_dcache_fsm = DCACHE_MISS_UPDT;
1180                        }
1181                        break;
1182                    }
1183                    if ( !r_dcache_miss_req && r_dcache_inval_rsp ) { // Miss read response and invalidation
1184                        if ( r_vci_rsp_data_error ) {
1185                            r_dcache_inval_rsp  = false;
1186                            r_dcache_fsm = DCACHE_ERROR;
1187                        } else {
1188                            r_dcache_inval_rsp  = false;
1189                            r_dcache_fsm = DCACHE_CC_CLEANUP;
1190                        }
1191                        break;
1192                    }
1193                    break;
1194                }
1195                //////////////////////
1196            case DCACHE_MISS_UPDT:
1197
1198                {
1199                        if ( r_tgt_dcache_req.read() ) {   // external request
1200                        r_dcache_fsm = DCACHE_CC_CHECK;
1201                        r_dcache_fsm_save = r_dcache_fsm;
1202                        break;
1203                    }
1204                    if( !r_dcache_cleanup_req.read() && !r_dcache_inval_rsp ){
1205                        vci_addr_t  ad  = 0;
1206                        ad = (vci_addr_t) r_dcache_addr_save.read();
1207                        data_t* buf = new data_t[m_dcache_words];
1208                        for(size_t i=0; i<m_dcache_words; i++) {
1209                            buf[i] = r_dcache_miss_buf[i];
1210                        }
1211                        vci_addr_t  victim_index = 0;
1212                        if ( dreq.valid ) m_cost_data_miss_frz++;
1213                        m_cpt_dcache_data_write++;
1214                        m_cpt_dcache_dir_write++;
1215
1216                        r_dcache_cleanup_req = r_dcache.update(ad, buf, &victim_index);
1217                        r_dcache_cleanup_line = (addr_40) victim_index;
1218
1219                        r_dcache_fsm = DCACHE_IDLE;
1220                        delete [] buf;
1221                        break;
1222                    }
1223                    if( r_dcache_inval_rsp ){
1224                        r_dcache_inval_rsp  = false;
1225                        r_dcache_fsm = DCACHE_CC_CLEANUP;
1226                        break;
1227                    }
1228                    break;
1229                }
1230                ////////////////////
1231            case DCACHE_UNC_WAIT:
1232                {
1233                    if ( dreq.valid ) m_cost_unc_read_frz++;
1234                    if ( r_tgt_dcache_req ) {   // external request
1235                        r_dcache_fsm = DCACHE_CC_CHECK;
1236                        r_dcache_fsm_save = r_dcache_fsm;
1237                        break;
1238                    }
1239                    if ( !r_dcache_unc_req ) {
1240                        if ( r_vci_rsp_data_error ) {
1241                            r_dcache_fsm = DCACHE_ERROR;
1242                        } else {
1243                            if(dreq.type == iss_t::DATA_LL){
1244                                r_dcache_ll_valid = true;
1245                                r_dcache_ll_data = r_dcache_miss_buf[0];
1246                                r_dcache_ll_addr = (vci_addr_t) dreq.addr;
1247                            }
1248                            r_dcache_fsm = DCACHE_IDLE;
1249                            drsp.valid = true;
1250                            drsp.rdata = r_dcache_miss_buf[0];
1251                        }
1252                    }
1253                    break;
1254                }
1255                ////////////////////
1256            case DCACHE_SC_WAIT:
1257                {
1258                    if ( dreq.valid ) m_cost_unc_read_frz++;
1259                    if ( r_tgt_dcache_req ) {   // external request
1260                        r_dcache_fsm = DCACHE_CC_CHECK;
1261                        r_dcache_fsm_save = r_dcache_fsm;
1262                        break;
1263                    }
1264                    if ( !r_dcache_sc_req ) {
1265                        if ( r_vci_rsp_data_error ) {
1266                            r_dcache_fsm = DCACHE_ERROR;
1267                        } else {
1268                            r_dcache_fsm = DCACHE_IDLE;
1269                            drsp.valid = true;
1270                            drsp.rdata = r_dcache_miss_buf[0];
1271                            r_dcache_ll_valid = false;
1272                        }
1273                    }
1274                    break;
1275                }
1276
1277                //////////////////
1278            case DCACHE_ERROR:
1279                {
1280                    r_dcache_fsm = DCACHE_IDLE;
1281                    r_vci_rsp_data_error = false;
1282                    drsp.error = true;
1283                    drsp.valid = true;
1284                    break;
1285                }
1286                /////////////////   
1287            case DCACHE_INVAL:
1288                {
1289                    if ( r_tgt_dcache_req.read() ) {   // external request
1290                        r_dcache_fsm = DCACHE_CC_CHECK;
1291                        r_dcache_fsm_save = r_dcache_fsm;
1292                        break;
1293                    }
1294                    if( !r_dcache_cleanup_req.read() ){
1295                        m_cpt_dcache_dir_read += m_dcache_ways;
1296                        vci_addr_t  ad  = r_dcache_addr_save.read();
1297                        r_dcache_cleanup_req = r_dcache.inval(ad);
1298                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> (uint32_log2(m_dcache_words)+2);
1299
1300                        r_dcache_fsm = DCACHE_IDLE;
1301                    }
1302                    break;
1303                }
1304                /////////////////////
1305            case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
1306                {
1307
1308                    m_cpt_dcache_dir_read += m_dcache_ways;
1309                    m_cpt_dcache_data_read += m_dcache_ways;
1310                    addr_40  ad           = r_tgt_addr;
1311                    data_t  dcache_rdata = 0;
1312
1313                    if(( ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) &&
1314                            ( (r_dcache_addr_save.read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) {
1315                        r_dcache_inval_rsp = true;
1316                        r_tgt_dcache_req = false;
1317                        if(r_tgt_update){    // Also send a cleanup and answer
1318                            r_tgt_dcache_rsp     = true;
1319                        } else {            // Also send a cleanup but don't answer
1320                            r_tgt_dcache_rsp     = false;
1321                        }
1322                        r_dcache_fsm = r_dcache_fsm_save;
1323                    } else {
1324                        bool    dcache_hit   = r_dcache.read(ad, &dcache_rdata);
1325#ifdef COHERENCE_DEBUG
1326                        std::cout << "PROC " << m_srcid_rw << " DCACHE_CC_CHECK, hit ? : " << dcache_hit << std::endl;
1327#endif
1328                        if ( dcache_hit && r_tgt_update ) {
1329                            // complete the line buffer in case of update
1330                            for(size_t i=0; i<m_dcache_words; i++){
1331                                data_t rdata = 0;
1332                                r_dcache.read(ad + i*4,&rdata);
1333                                data_t mask = vci_param::be2mask(r_tgt_be[i]);
1334                                r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata);
1335                            }
1336                            r_dcache_fsm = DCACHE_CC_UPDT;
1337                        } else if ( dcache_hit && !r_tgt_update ) {
1338                            r_dcache_fsm = DCACHE_CC_INVAL;
1339                        } else {
1340                            if(r_tgt_update){
1341                                r_tgt_dcache_rsp = true;
1342                            } else {
1343                                r_tgt_dcache_rsp = false;
1344                            }
1345                            r_tgt_dcache_req = false;
1346                            r_dcache_fsm = r_dcache_fsm_save;
1347                        }
1348                    }
1349                    break;
1350                }
1351                ///////////////////
1352            case DCACHE_CC_UPDT:    // update directory and data cache       
1353                {
1354                    m_cpt_dcache_dir_write++;
1355                    m_cpt_dcache_data_write++;
1356                    addr_40  ad      = r_tgt_addr;
1357                    data_t* buf     = r_tgt_buf;
1358#ifdef COHERENCE_DEBUG
1359                    std::cout << "PROC " << m_srcid_rw << " DCACHE_CC_UPDT, update : " << std::endl;
1360#endif
1361                    for(size_t i=0; i<m_dcache_words; i++){
1362                        if(r_tgt_be[i]) {
1363                            r_dcache.write( ad + i*4, buf[i]);
1364#ifdef COHERENCE_DEBUG
1365                            std::cout << " address " << std::hex << ad+i*4 << " data " << std::dec << buf[i] << std::endl;
1366                            data_t rdata = 0xAAAAAAAA;
1367                            r_dcache.read(ad + i*4,&rdata);
1368                            std::cout << "data written " << rdata << std::endl;
1369#endif
1370                        }
1371                    }
1372                    r_tgt_dcache_req = false;
1373                    r_tgt_dcache_rsp = true;
1374                    r_dcache_fsm = r_dcache_fsm_save;
1375                    break;
1376                }
1377                /////////////////////
1378            case DCACHE_CC_INVAL:   // invalidate a cache line
1379                {
1380                    addr_40  ad      = r_tgt_addr;
1381                    r_tgt_dcache_rsp = true;
1382                    r_dcache.inval(ad);
1383                    r_tgt_dcache_req = false;
1384                    r_dcache_fsm = r_dcache_fsm_save;
1385                    break;
1386                }
1387                ///////////////////
1388            case DCACHE_CC_CLEANUP:   
1389                {
1390                    // external cache invalidate request
1391                    if ( r_tgt_dcache_req )   
1392                    {
1393                        r_dcache_fsm = DCACHE_CC_CHECK;
1394                        r_dcache_fsm_save = r_dcache_fsm;
1395                        break;
1396                    }       
1397                    // cleanup
1398                    if(!r_dcache_cleanup_req){
1399                        r_dcache_cleanup_req = true;
1400                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> (uint32_log2(m_dcache_words) + 2);
1401                        r_dcache_fsm = DCACHE_IDLE;
1402                    }
1403                    break;
1404                }   
1405
1406        } // end switch r_dcache_fsm
1407
1408#if DEBUG_CC_XCACHE_WRAPPER
1409        std::cout << " Data Response: " << drsp << std::endl;
1410#endif
1411
1412        /////////// execute one iss cycle /////////////////////////////////////////////
1413        {
1414            uint32_t it = 0;
1415            for (size_t i=0; i<(size_t)iss_t::n_irq; i++)
1416                if(p_irq[i].read()) it |= (1<<i);
1417            m_iss.executeNCycles(1, irsp, drsp, it);
1418        }
1419
1420        if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) ) m_cpt_frz_cycles++;
1421
1422
1423        ////////////////////////////////////////////////////////////////////////////
1424        // The VCI_CMD FSM controls the following ressources:
1425        // - r_vci_cmd_fsm
1426        // - r_vci_cmd_min
1427        // - r_vci_cmd_max
1428        // - r_vci_cmd_cpt
1429        // - wbuf reset
1430        //
1431        // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
1432        // There is 7 request types, with the following priorities :
1433        // 1 - Instruction Miss     : r_icache_miss_req
1434        // 2 - Data Write           : r_dcache_write_req
1435        // 3 - Data Read Miss       : r_dcache_miss_req
1436        // 4 - Data Read Uncached   : r_dcache_unc_req
1437        // 5 - Instruction Cleanup  : r_icache_cleanup_req
1438        // 6 - Data Cleanup         : r_dcache_cleanup_req
1439        // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM
1440        // and RSP_FSM exit simultaneously the IDLE state.
1441        //
1442        // VCI formats:
1443        // According to the VCI advanced specification, all read requests packets
1444        // (read Uncached, Miss data, Miss instruction) are one word packets.
1445        // For write burst packets, all words must be in the same cache line,
1446        // and addresses must be contiguous (the BE field is 0 in case of "holes").
1447        //////////////////////////////////////////////////////////////////////////////
1448
1449        switch (r_vci_cmd_fsm) {
1450
1451            case CMD_IDLE:
1452                if (r_vci_rsp_fsm != RSP_IDLE) break;
1453
1454                r_vci_cmd_cpt = 0;
1455                if ( r_icache_cleanup_req ) {
1456                    r_vci_cmd_fsm = CMD_INS_CLEANUP;
1457                } else if ( r_dcache_cleanup_req ) {
1458                    r_vci_cmd_fsm = CMD_DATA_CLEANUP;
1459                } else if ( r_icache_miss_req ) {
1460                    r_vci_cmd_fsm = CMD_INS_MISS;
1461                    m_cpt_imiss_transaction++;
1462                } else if ( r_icache_unc_req ) {
1463                    r_vci_cmd_fsm = CMD_INS_UNC;
1464                    m_cpt_imiss_transaction++;
1465                } else if ( r_dcache_write_req ) {
1466                    r_vci_cmd_fsm = CMD_DATA_WRITE;
1467                    r_vci_cmd_cpt = r_wbuf.getMin();
1468                    r_vci_cmd_min = r_wbuf.getMin();
1469                    r_vci_cmd_max = r_wbuf.getMax();
1470                    m_cpt_write_transaction++;
1471                    m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1);
1472                } else if ( r_dcache_miss_req ) {
1473                    r_vci_cmd_fsm = CMD_DATA_MISS;
1474                    m_cpt_dmiss_transaction++;
1475                } else if ( r_dcache_unc_req ) {
1476                    r_vci_cmd_fsm = CMD_DATA_UNC;
1477                    m_cpt_unc_transaction++;
1478                } else if ( r_dcache_sc_req ) {
1479                    r_vci_cmd_fsm = CMD_DATA_SC;
1480                    r_vci_cmd_max = 1;
1481                    m_cpt_unc_transaction++;
1482                }
1483                break;
1484
1485            case CMD_DATA_WRITE:
1486                if ( p_vci_ini_rw.cmdack.read() ) {
1487                    r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
1488                    if (r_vci_cmd_cpt == r_vci_cmd_max) {
1489                        r_vci_cmd_fsm = CMD_IDLE ;
1490                        r_wbuf.reset() ;
1491                    }
1492                }
1493                break;
1494
1495            case CMD_DATA_SC:
1496                if ( p_vci_ini_rw.cmdack.read() ) {
1497                    r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
1498                    if (r_vci_cmd_cpt == r_vci_cmd_max) {
1499                        r_vci_cmd_fsm = CMD_IDLE ;
1500                    }
1501                }
1502                break;
1503            case CMD_INS_MISS:
1504            case CMD_INS_UNC:
1505            case CMD_DATA_MISS:
1506            case CMD_DATA_UNC:
1507                if ( p_vci_ini_rw.cmdack.read() ) {
1508                    r_vci_cmd_fsm = CMD_IDLE;
1509                }
1510                break;
1511            case CMD_INS_CLEANUP:
1512            case CMD_DATA_CLEANUP:
1513                if ( p_vci_ini_c.cmdack.read() ) {
1514                    r_vci_cmd_fsm = CMD_IDLE;
1515                }
1516                break;
1517
1518        } // end  switch r_vci_cmd_fsm
1519
1520        //////////////////////////////////////////////////////////////////////////
1521        // The VCI_RSP FSM controls the following ressources:
1522        // - r_vci_rsp_fsm:
1523        // - r_icache_miss_buf[m_icache_words]
1524        // - r_dcache_miss_buf[m_dcache_words]
1525        // - r_icache_miss_req reset
1526        // - r_icache_unc_req reset
1527        // - r_dcache_miss_req reset
1528        // - r_icache_cleanup_req reset
1529        // - r_dcache_cleanup_req reset
1530        // - r_vci_rsp_data_error set
1531        // - r_vci_rsp_ins_error set
1532        // - r_vci_rsp_cpt
1533        // In order to have only one active VCI transaction, this VCI_RSP_FSM
1534        // is synchronized with the VCI_CMD FSM, and both FSMs exit the
1535        // IDLE state simultaneously.
1536        //
1537        // VCI formats:
1538        // This component accepts single word or multi-word response packets for
1539        // write response packets.
1540        //
1541        // Error handling:
1542        // This FSM analyzes the VCI error code and signals directly the
1543        // Write Bus Error.
1544        // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error
1545        // flip_flop and the error is signaled by the DCACHE FSM. 
1546        // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
1547        // flip_flop and the error is signaled by the DCACHE FSM. 
1548        // In case of Cleanup Error, the simulation stops with an error message...
1549        //////////////////////////////////////////////////////////////////////////
1550
1551        switch (r_vci_rsp_fsm) {
1552
1553            case RSP_IDLE:
1554                if(p_vci_ini_rw.rspval.read()||
1555                        p_vci_ini_c.rspval.read())
1556                {
1557                    std::cout << "CC_XCache " << m_srcid_rw << " Unexpected response" << std::endl;
1558                }
1559                assert( ! p_vci_ini_rw.rspval.read() && ! p_vci_ini_c.rspval.read() && "Unexpected response" );
1560                if (r_vci_cmd_fsm != CMD_IDLE) break;
1561
1562                r_vci_rsp_cpt = 0;
1563                if      ( r_icache_cleanup_req )    r_vci_rsp_fsm = RSP_INS_CLEANUP;
1564                else if ( r_dcache_cleanup_req )    r_vci_rsp_fsm = RSP_DATA_CLEANUP;
1565                else if ( r_icache_miss_req )       r_vci_rsp_fsm = RSP_INS_MISS;
1566                else if ( r_icache_unc_req )        r_vci_rsp_fsm = RSP_INS_UNC;
1567                else if ( r_dcache_write_req )      r_vci_rsp_fsm = RSP_DATA_WRITE;
1568                else if ( r_dcache_miss_req )       r_vci_rsp_fsm = RSP_DATA_MISS;
1569                else if ( r_dcache_unc_req )        r_vci_rsp_fsm = RSP_DATA_UNC;
1570                else if ( r_dcache_sc_req )         r_vci_rsp_fsm = RSP_DATA_SC;
1571                break;
1572
1573            case RSP_INS_MISS:
1574                m_cost_imiss_transaction++;
1575                if ( ! p_vci_ini_rw.rspval.read() )
1576                    break;
1577                assert( (r_vci_rsp_cpt < m_icache_words) &&
1578                        "The VCI response packet for instruction miss is too long" );
1579                r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
1580                r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
1581
1582                if ( p_vci_ini_rw.reop.read() ) {
1583                    assert( ((r_vci_rsp_cpt == m_icache_words - 1) ||
1584                             p_vci_ini_rw.rerror.read() ||
1585                             (r_vci_rsp_ins_error.read()&0x1))&&
1586                            "The VCI response packet for instruction miss is too short");
1587                    r_icache_miss_req = false;
1588                    r_vci_rsp_fsm = RSP_IDLE;
1589                }
1590                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
1591                break;
1592
1593            case RSP_INS_UNC:
1594                m_cost_imiss_transaction++;
1595                if ( ! p_vci_ini_rw.rspval.read() )
1596                    break;
1597                assert(p_vci_ini_rw.reop.read() &&
1598                        "illegal VCI response packet for uncached instruction");
1599                r_icache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
1600                r_vci_rsp_fsm = RSP_IDLE;
1601                r_icache_unc_req = false;
1602                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
1603                break;
1604
1605            case RSP_DATA_MISS:
1606                m_cost_dmiss_transaction++;
1607                if ( ! p_vci_ini_rw.rspval.read() )
1608                    break;
1609                assert(r_vci_rsp_cpt != m_dcache_words &&
1610                        "illegal VCI response packet for data read miss");
1611                r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
1612                r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
1613                if ( p_vci_ini_rw.reop.read() ) {
1614                    assert( ((r_vci_rsp_cpt == m_dcache_words - 1)
1615                             || (p_vci_ini_rw.rerror.read()&0x1)
1616                             || r_vci_rsp_data_error.read()) &&
1617                            "illegal VCI response packet for data read miss");
1618                    r_dcache_miss_req = false;
1619                    r_vci_rsp_fsm = RSP_IDLE;
1620                }
1621                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
1622                break;
1623
1624            case RSP_DATA_WRITE:
1625                m_cost_write_transaction++;
1626                if ( ! p_vci_ini_rw.rspval.read() )
1627                    break;
1628                if ( p_vci_ini_rw.reop.read() ) {
1629                    r_vci_rsp_fsm = RSP_IDLE;
1630                    r_dcache_write_req = false;
1631                }
1632                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) m_iss.setWriteBerr();
1633                break;
1634
1635            case RSP_DATA_UNC:
1636                m_cost_unc_transaction++;
1637                if ( ! p_vci_ini_rw.rspval.read() )
1638                    break;
1639                assert(p_vci_ini_rw.reop.read() &&
1640                        "illegal VCI response packet for data read uncached");
1641                r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
1642                r_vci_rsp_fsm = RSP_IDLE;
1643                r_dcache_unc_req = false;
1644                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
1645                break;
1646
1647            case RSP_DATA_SC:
1648                m_cost_unc_transaction++;
1649                if ( ! p_vci_ini_rw.rspval.read() )
1650                    break;
1651                assert(p_vci_ini_rw.reop.read() &&
1652                        "illegal VCI response packet for data SC");
1653                r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
1654                r_vci_rsp_fsm = RSP_IDLE;
1655                r_dcache_sc_req = false;
1656                if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
1657                break;
1658
1659            case RSP_INS_CLEANUP:
1660            case RSP_DATA_CLEANUP:
1661                if ( ! p_vci_ini_c.rspval.read() )
1662                    break;
1663                assert( p_vci_ini_c.reop.read() &&
1664                        "illegal VCI response packet for icache cleanup");
1665                assert( ((p_vci_ini_c.rerror.read()&0x1) == vci_param::ERR_NORMAL) &&
1666                        "error in response packet for icache cleanup");
1667                if ( r_vci_rsp_fsm == RSP_INS_CLEANUP ) r_icache_cleanup_req = false;
1668                else                                    r_dcache_cleanup_req = false;
1669                r_vci_rsp_fsm = RSP_IDLE;
1670                break;
1671
1672        } // end switch r_vci_rsp_fsm
1673
1674    } // end transition()
1675
1676    //////////////////////////////////////////////////////////////////////////////////
1677    tmpl(void)::genMoore()
1678    //////////////////////////////////////////////////////////////////////////////////
1679    {
1680        // VCI initiator response
1681
1682        p_vci_ini_rw.rspack = true;
1683        p_vci_ini_c.rspack = true;
1684
1685        // VCI initiator command
1686
1687        switch (r_vci_cmd_fsm.read() ) {
1688
1689            case CMD_IDLE:
1690                p_vci_ini_rw.cmdval  = false;
1691                p_vci_ini_rw.address = 0;
1692                p_vci_ini_rw.wdata   = 0;
1693                p_vci_ini_rw.be      = 0;
1694                p_vci_ini_rw.plen    = 0;
1695                p_vci_ini_rw.cmd     = vci_param::CMD_NOP;
1696                p_vci_ini_rw.trdid   = 0;
1697                p_vci_ini_rw.pktid   = 0;
1698                p_vci_ini_rw.srcid   = 0;
1699                p_vci_ini_rw.cons    = false;
1700                p_vci_ini_rw.wrap    = false;
1701                p_vci_ini_rw.contig  = false;
1702                p_vci_ini_rw.clen    = 0;
1703                p_vci_ini_rw.cfixed  = false;
1704                p_vci_ini_rw.eop     = false;
1705
1706                p_vci_ini_c.cmdval  = false;
1707                p_vci_ini_c.address = 0;
1708                p_vci_ini_c.wdata  = 0;
1709                p_vci_ini_c.be     = 0;
1710                p_vci_ini_c.plen   = 0;
1711                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
1712                p_vci_ini_c.trdid  = 0;
1713                p_vci_ini_c.pktid  = 0;
1714                p_vci_ini_c.srcid  = 0;
1715                p_vci_ini_c.cons   = false;
1716                p_vci_ini_c.wrap   = false;
1717                p_vci_ini_c.contig = false;
1718                p_vci_ini_c.clen   = 0;
1719                p_vci_ini_c.cfixed = false;
1720                p_vci_ini_c.eop = false;
1721
1722                break;
1723
1724            case CMD_DATA_UNC:
1725                p_vci_ini_rw.cmdval = true;
1726                p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
1727                switch( r_dcache_type_save ) {
1728                    case iss_t::DATA_READ:
1729                        p_vci_ini_rw.wdata = 0;
1730                        p_vci_ini_rw.be  = r_dcache_be_save.read();
1731                        p_vci_ini_rw.cmd = vci_param::CMD_READ;
1732                        break;
1733                    case iss_t::DATA_LL:
1734                        p_vci_ini_rw.wdata = 0;
1735                        p_vci_ini_rw.be  = 0xF;
1736                        p_vci_ini_rw.cmd = vci_param::CMD_LOCKED_READ;
1737                        break;
1738                    default:
1739                        assert("this should not happen");
1740                }
1741                p_vci_ini_rw.plen = 4;
1742                p_vci_ini_rw.trdid  = 0;   // data cache uncached read
1743                p_vci_ini_rw.pktid  = 0;
1744                p_vci_ini_rw.srcid  = m_srcid_rw;
1745                p_vci_ini_rw.cons   = false;
1746                p_vci_ini_rw.wrap   = false;
1747                p_vci_ini_rw.contig = true;
1748                p_vci_ini_rw.clen   = 0;
1749                p_vci_ini_rw.cfixed = false;
1750                p_vci_ini_rw.eop    = true;
1751
1752                p_vci_ini_c.cmdval  = false;
1753                p_vci_ini_c.address = 0;
1754                p_vci_ini_c.wdata  = 0;
1755                p_vci_ini_c.be     = 0;
1756                p_vci_ini_c.plen   = 0;
1757                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
1758                p_vci_ini_c.trdid  = 0;
1759                p_vci_ini_c.pktid  = 0;
1760                p_vci_ini_c.srcid  = 0;
1761                p_vci_ini_c.cons   = false;
1762                p_vci_ini_c.wrap   = false;
1763                p_vci_ini_c.contig = false;
1764                p_vci_ini_c.clen   = 0;
1765                p_vci_ini_c.cfixed = false;
1766                p_vci_ini_c.eop = false;
1767
1768                break;
1769
1770            case CMD_DATA_SC:
1771                p_vci_ini_rw.cmdval = true;
1772                p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
1773                if(r_vci_cmd_max.read() == 3){
1774                    assert(false && "Not handled yet");
1775                } else { // r_vci_cmd_cpt == 1
1776                    switch(r_vci_cmd_cpt.read()){
1777                        case 0:
1778                            p_vci_ini_rw.wdata = (uint32_t)(r_dcache_ll_data.read() & 0xFFFFFFFF);
1779                            break;
1780                        case 1:
1781                            p_vci_ini_rw.wdata = r_dcache_wdata_save.read();
1782                            break;
1783                    }
1784                }
1785                p_vci_ini_rw.be     = 0xF;
1786                p_vci_ini_rw.cmd    = vci_param::CMD_STORE_COND;
1787                p_vci_ini_rw.plen   = 4*(r_vci_cmd_max.read()+1);
1788                p_vci_ini_rw.trdid  = 0;   // data cache uncached read
1789                p_vci_ini_rw.pktid  = 0;
1790                p_vci_ini_rw.srcid  = m_srcid_rw;
1791                p_vci_ini_rw.cons   = true;
1792                p_vci_ini_rw.wrap   = false;
1793                p_vci_ini_rw.contig = false;
1794                p_vci_ini_rw.clen   = 0;
1795                p_vci_ini_rw.cfixed = false;
1796                p_vci_ini_rw.eop    = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
1797
1798                p_vci_ini_c.cmdval  = false;
1799                p_vci_ini_c.address = 0;
1800                p_vci_ini_c.wdata  = 0;
1801                p_vci_ini_c.be     = 0;
1802                p_vci_ini_c.plen   = 0;
1803                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
1804                p_vci_ini_c.trdid  = 0;
1805                p_vci_ini_c.pktid  = 0;
1806                p_vci_ini_c.srcid  = 0;
1807                p_vci_ini_c.cons   = false;
1808                p_vci_ini_c.wrap   = false;
1809                p_vci_ini_c.contig = false;
1810                p_vci_ini_c.clen   = 0;
1811                p_vci_ini_c.cfixed = false;
1812                p_vci_ini_c.eop = false;
1813
1814                break;
1815
1816            case CMD_DATA_WRITE:
1817                p_vci_ini_rw.cmdval  = true;
1818                p_vci_ini_rw.address = r_wbuf.getAddress(r_vci_cmd_cpt)&~0x3;
1819                p_vci_ini_rw.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
1820                p_vci_ini_rw.be      = r_wbuf.getBe(r_vci_cmd_cpt);
1821                p_vci_ini_rw.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
1822                p_vci_ini_rw.cmd     = vci_param::CMD_WRITE;
1823                p_vci_ini_rw.trdid   = 0;  // data cache write
1824                p_vci_ini_rw.pktid   = 0;
1825                p_vci_ini_rw.srcid   = m_srcid_rw;
1826                p_vci_ini_rw.cons    = false;
1827                p_vci_ini_rw.wrap    = false;
1828                p_vci_ini_rw.contig  = true;
1829                p_vci_ini_rw.clen    = 0;
1830                p_vci_ini_rw.cfixed  = false;
1831                p_vci_ini_rw.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
1832
1833                p_vci_ini_c.cmdval  = false;
1834                p_vci_ini_c.address = 0;
1835                p_vci_ini_c.wdata  = 0;
1836                p_vci_ini_c.be     = 0;
1837                p_vci_ini_c.plen   = 0;
1838                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
1839                p_vci_ini_c.trdid  = 0;
1840                p_vci_ini_c.pktid  = 0;
1841                p_vci_ini_c.srcid  = 0;
1842                p_vci_ini_c.cons   = false;
1843                p_vci_ini_c.wrap   = false;
1844                p_vci_ini_c.contig = false;
1845                p_vci_ini_c.clen   = 0;
1846                p_vci_ini_c.cfixed = false;
1847                p_vci_ini_c.eop = false;
1848
1849                break;
1850
1851            case CMD_DATA_MISS:
1852                p_vci_ini_rw.cmdval = true;
1853                p_vci_ini_rw.address = r_dcache_addr_save.read() & (addr_40) m_dcache_yzmask;
1854                p_vci_ini_rw.be     = 0xF;
1855                p_vci_ini_rw.plen   = m_dcache_words << 2;
1856                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
1857                p_vci_ini_rw.trdid  = 1;   // data cache cached read
1858                p_vci_ini_rw.pktid  = 0;
1859                p_vci_ini_rw.srcid  = m_srcid_rw;
1860                p_vci_ini_rw.cons   = false;
1861                p_vci_ini_rw.wrap   = false;
1862                p_vci_ini_rw.contig = true;
1863                p_vci_ini_rw.clen   = 0;
1864                p_vci_ini_rw.cfixed = false;
1865                p_vci_ini_rw.eop = true;
1866
1867                p_vci_ini_c.cmdval  = false;
1868                p_vci_ini_c.address = 0;
1869                p_vci_ini_c.wdata  = 0;
1870                p_vci_ini_c.be     = 0;
1871                p_vci_ini_c.plen   = 0;
1872                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
1873                p_vci_ini_c.trdid  = 0;
1874                p_vci_ini_c.pktid  = 0;
1875                p_vci_ini_c.srcid  = 0;
1876                p_vci_ini_c.cons   = false;
1877                p_vci_ini_c.wrap   = false;
1878                p_vci_ini_c.contig = false;
1879                p_vci_ini_c.clen   = 0;
1880                p_vci_ini_c.cfixed = false;
1881                p_vci_ini_c.eop = false;
1882
1883                break;
1884
1885            case CMD_INS_MISS:
1886                p_vci_ini_rw.cmdval = true;
1887                p_vci_ini_rw.address = r_icache_addr_save.read() & (addr_40) m_icache_yzmask;
1888                p_vci_ini_rw.be     = 0xF;
1889                p_vci_ini_rw.plen   = m_icache_words << 2;
1890                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
1891                p_vci_ini_rw.trdid  = 3;   // ins cache cached read
1892                p_vci_ini_rw.pktid  = 0;
1893                p_vci_ini_rw.srcid  = m_srcid_rw;
1894                p_vci_ini_rw.cons   = false;
1895                p_vci_ini_rw.wrap   = false;
1896                p_vci_ini_rw.contig = true;
1897                p_vci_ini_rw.clen   = 0;
1898                p_vci_ini_rw.cfixed = false;
1899                p_vci_ini_rw.eop = true;
1900
1901                p_vci_ini_c.cmdval  = false;
1902                p_vci_ini_c.address = 0;
1903                p_vci_ini_c.wdata  = 0;
1904                p_vci_ini_c.be     = 0;
1905                p_vci_ini_c.plen   = 0;
1906                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
1907                p_vci_ini_c.trdid  = 0;
1908                p_vci_ini_c.pktid  = 0;
1909                p_vci_ini_c.srcid  = 0;
1910                p_vci_ini_c.cons   = false;
1911                p_vci_ini_c.wrap   = false;
1912                p_vci_ini_c.contig = false;
1913                p_vci_ini_c.clen   = 0;
1914                p_vci_ini_c.cfixed = false;
1915                p_vci_ini_c.eop = false;
1916
1917                break;
1918
1919            case CMD_INS_UNC:
1920                p_vci_ini_rw.cmdval = true;
1921                p_vci_ini_rw.address = r_icache_addr_save.read() & ~0x3;
1922                p_vci_ini_rw.be     = 0xF;
1923                p_vci_ini_rw.plen   = 4;
1924                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
1925                p_vci_ini_rw.trdid  = 2;   // ins cache uncached read
1926                p_vci_ini_rw.pktid  = 0;
1927                p_vci_ini_rw.srcid  = m_srcid_rw;
1928                p_vci_ini_rw.cons   = false;
1929                p_vci_ini_rw.wrap   = false;
1930                p_vci_ini_rw.contig = true;
1931                p_vci_ini_rw.clen   = 0;
1932                p_vci_ini_rw.cfixed = false;
1933                p_vci_ini_rw.eop = true;
1934
1935                p_vci_ini_c.cmdval  = false;
1936                p_vci_ini_c.address = 0;
1937                p_vci_ini_c.wdata  = 0;
1938                p_vci_ini_c.be     = 0;
1939                p_vci_ini_c.plen   = 0;
1940                p_vci_ini_c.cmd    = vci_param::CMD_NOP;
1941                p_vci_ini_c.trdid  = 0;
1942                p_vci_ini_c.pktid  = 0;
1943                p_vci_ini_c.srcid  = 0;
1944                p_vci_ini_c.cons   = false;
1945                p_vci_ini_c.wrap   = false;
1946                p_vci_ini_c.contig = false;
1947                p_vci_ini_c.clen   = 0;
1948                p_vci_ini_c.cfixed = false;
1949                p_vci_ini_c.eop = false;
1950
1951
1952                break;
1953
1954            case CMD_INS_CLEANUP:
1955                p_vci_ini_rw.cmdval = false;
1956                p_vci_ini_rw.address = 0;
1957                p_vci_ini_rw.wdata  = 0;
1958                p_vci_ini_rw.be     = 0;
1959                p_vci_ini_rw.plen   = 0;
1960                p_vci_ini_rw.cmd    = vci_param::CMD_NOP;
1961                p_vci_ini_rw.trdid  = 0;
1962                p_vci_ini_rw.pktid  = 0;
1963                p_vci_ini_rw.srcid  = 0;
1964                p_vci_ini_rw.cons   = false;
1965                p_vci_ini_rw.wrap   = false;
1966                p_vci_ini_rw.contig = false;
1967                p_vci_ini_rw.clen   = 0;
1968                p_vci_ini_rw.cfixed = false;
1969                p_vci_ini_rw.eop    = false;
1970
1971                p_vci_ini_c.cmdval  = true;
1972                p_vci_ini_c.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
1973                p_vci_ini_c.wdata  = 0;
1974                p_vci_ini_c.be     = 0;
1975                p_vci_ini_c.plen   = 4;
1976                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
1977                p_vci_ini_c.trdid  = 1; // cleanup instruction
1978                p_vci_ini_c.pktid  = 0;
1979                p_vci_ini_c.srcid  = m_srcid_c;
1980                p_vci_ini_c.cons   = false;
1981                p_vci_ini_c.wrap   = false;
1982                p_vci_ini_c.contig = false;
1983                p_vci_ini_c.clen   = 0;
1984                p_vci_ini_c.cfixed = false;
1985                p_vci_ini_c.eop = true;
1986
1987                break;
1988
1989
1990            case CMD_DATA_CLEANUP:
1991                p_vci_ini_rw.cmdval = false;
1992                p_vci_ini_rw.address = 0;
1993                p_vci_ini_rw.wdata  = 0;
1994                p_vci_ini_rw.be     = 0;
1995                p_vci_ini_rw.plen   = 0;
1996                p_vci_ini_rw.cmd    = vci_param::CMD_NOP;
1997                p_vci_ini_rw.trdid  = 0;
1998                p_vci_ini_rw.pktid  = 0;
1999                p_vci_ini_rw.srcid  = 0;
2000                p_vci_ini_rw.cons   = false;
2001                p_vci_ini_rw.wrap   = false;
2002                p_vci_ini_rw.contig = false;
2003                p_vci_ini_rw.clen   = 0;
2004                p_vci_ini_rw.cfixed = false;
2005                p_vci_ini_rw.eop    = false;
2006
2007                p_vci_ini_c.cmdval  = true;
2008                p_vci_ini_c.address = r_dcache_cleanup_line.read() * (m_dcache_words<<2);
2009                p_vci_ini_c.wdata  = 0;
2010                p_vci_ini_c.be     = 0;
2011                p_vci_ini_c.plen   = 4;
2012                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
2013                p_vci_ini_c.trdid  = 0; // cleanup data
2014                p_vci_ini_c.pktid  = 0;
2015                p_vci_ini_c.srcid  = m_srcid_c;
2016                p_vci_ini_c.cons   = false;
2017                p_vci_ini_c.wrap   = false;
2018                p_vci_ini_c.contig = false;
2019                p_vci_ini_c.clen   = 0;
2020                p_vci_ini_c.cfixed = false;
2021                p_vci_ini_c.eop = true;
2022
2023                break;
2024
2025        } // end switch r_vci_cmd_fsm
2026
2027        // VCI_TGT
2028
2029        switch ( r_vci_tgt_fsm.read() ) {
2030
2031            case TGT_IDLE:
2032            case TGT_UPDT_WORD:
2033            case TGT_UPDT_DATA:
2034                p_vci_tgt.cmdack  = true;
2035                p_vci_tgt.rspval  = false;
2036                break;
2037
2038            case TGT_RSP_BROADCAST:
2039                p_vci_tgt.cmdack  = false;
2040                p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
2041                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
2042                p_vci_tgt.rpktid  = r_tgt_pktid.read();
2043                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
2044                p_vci_tgt.rdata   = 0;
2045                p_vci_tgt.rerror  = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
2046                p_vci_tgt.reop    = true;
2047                break;
2048
2049            case TGT_RSP_ICACHE:
2050                p_vci_tgt.cmdack  = false;
2051                p_vci_tgt.rspval  = !r_tgt_icache_req.read() && r_tgt_icache_rsp.read();
2052                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
2053                p_vci_tgt.rpktid  = r_tgt_pktid.read();
2054                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
2055                p_vci_tgt.rdata   = 0;
2056                p_vci_tgt.rerror  = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
2057                p_vci_tgt.reop    = true;
2058                break;
2059
2060            case TGT_RSP_DCACHE:
2061                p_vci_tgt.cmdack  = false;
2062                p_vci_tgt.rspval  = !r_tgt_dcache_req.read() && r_tgt_dcache_rsp.read();
2063                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
2064                p_vci_tgt.rpktid  = r_tgt_pktid.read();
2065                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
2066                p_vci_tgt.rdata   = 0;
2067                p_vci_tgt.rerror  = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
2068                p_vci_tgt.reop    = true;
2069                break;
2070
2071            case TGT_REQ_BROADCAST:
2072            case TGT_REQ_ICACHE:
2073            case TGT_REQ_DCACHE:
2074                p_vci_tgt.cmdack  = false;
2075                p_vci_tgt.rspval  = false;
2076                break;
2077
2078        } // end switch TGT_FSM
2079    } // end genMoore()
2080
2081}} // end namespace
2082
2083// Local Variables:
2084// tab-width: 4
2085// c-basic-offset: 4
2086// c-file-offsets:((innamespace . 0)(inline-open . 0))
2087// indent-tabs-mode: nil
2088// End:
2089
2090// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
2091
2092
2093
2094
Note: See TracBrowser for help on using the repository browser.