source: trunk/modules/vci_cc_xcache_wrapper/caba/source/src/vci_cc_xcache_wrapper.cpp @ 2

Last change on this file since 2 was 2, checked in by nipo, 14 years ago

Import TSAR modules in TSAR's own svn

  • 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: 59.1 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.h"
60
61#define DEBUG_CC_XCACHE_WRAPPER 0
62
63namespace soclib {
64namespace caba {
65
66#if DEBUG_CC_XCACHE_WRAPPER
67namespace {
68const char *dcache_fsm_state_str[] = {
69    "DCACHE_IDLE",
70    "DCACHE_WRITE_UPDT",
71    "DCACHE_WRITE_REQ",
72    "DCACHE_MISS_WAIT",
73    "DCACHE_MISS_UPDT",
74    "DCACHE_UNC_WAIT",
75    "DCACHE_INVAL",
76    "DCACHE_ERROR",
77    "DCACHE_CC_CHECK",
78    "DCACHE_CC_INVAL",
79    "DCACHE_CC_UPDT",
80    "DCACHE_CC_NOP",
81};
82const 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_INVAL",
89};
90const char *cmd_fsm_state_str[] = {
91    "CMD_IDLE",
92    "CMD_INS_MISS",
93    "CMD_INS_UNC",
94    "CMD_DATA_MISS",
95    "CMD_DATA_UNC",
96    "CMD_DATA_WRITE",
97};
98const char *rsp_fsm_state_str[] = {
99    "RSP_IDLE",
100    "RSP_INS_MISS",
101    "RSP_INS_UNC",
102    "RSP_DATA_MISS",
103    "RSP_DATA_UNC",
104    "RSP_DATA_WRITE",
105};
106const char *tgt_fsm_state_str[] = {
107    "TGT_IDLE",
108    "TGT_UPDT_WORD",
109    "TGT_UPDT_DATA",
110    "TGT_REQ_BROADCAST",
111    "TGT_REQ_DCACHE",
112    "TGT_RSP_BROADCAST",
113    "TGT_RSP_DCACHE",
114};
115}
116#endif
117
118#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXcacheWrapper<vci_param, iss_t>
119
120using soclib::common::uint32_log2;
121
122/////////////////////////////////
123tmpl(/**/)::VciCcXcacheWrapper(
124                               /////////////////////////////////
125                               sc_module_name name,
126                               int proc_id,
127                               const soclib::common::MappingTable &mtp,
128                               const soclib::common::MappingTable &mtc,
129                               const soclib::common::IntTab &initiator_index,
130                               const soclib::common::IntTab &target_index,
131                               size_t icache_ways,
132                               size_t icache_sets,
133                               size_t icache_words,
134                               size_t dcache_ways,
135                               size_t dcache_sets,
136                               size_t dcache_words,
137                               addr_t cleanup_offset )
138           :
139           soclib::caba::BaseModule(name),
140
141           p_clk("clk"),
142           p_resetn("resetn"),
143           p_vci_ini("vci_ini"),
144           p_vci_tgt("vci_tgt"),
145
146           m_cacheability_table(mtp.getCacheabilityTable()),
147           m_segment(mtc.getSegment(target_index)),
148           m_iss(this->name(), proc_id),
149           m_srcid(mtp.indexForId(initiator_index)),
150           m_cleanup_address(cleanup_offset),
151
152           m_dcache_ways(dcache_ways),
153           m_dcache_words(dcache_words),
154           m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
155           m_icache_ways(icache_ways),
156           m_icache_words(icache_words),
157           m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
158
159           r_dcache_fsm("r_dcache_fsm"),
160           r_dcache_fsm_save("r_dcache_fsm_save"),
161           r_dcache_addr_save("r_dcache_addr_save"),
162           r_dcache_wdata_save("r_dcache_wdata_save"),
163           r_dcache_rdata_save("r_dcache_rdata_save"),
164           r_dcache_type_save("r_dcache_type_save"),
165           r_dcache_be_save("r_dcache_be_save"),
166           r_dcache_cached_save("r_dcache_cached_save"),
167           r_dcache_cleanup_req("r_dcache_cleanup_req"),
168           r_dcache_cleanup_line("r_dcache_cleanup_line"),
169           r_dcache_miss_req("r_dcache_miss_req"),
170           r_dcache_unc_req("r_dcache_unc_req"),
171           r_dcache_write_req("r_dcache_write_req"),
172
173           r_icache_fsm("r_icache_fsm"),
174           r_icache_fsm_save("r_icache_fsm_save"),
175           r_icache_addr_save("r_icache_addr_save"),
176           r_icache_miss_req("r_icache_miss_req"),
177           r_icache_cleanup_req("r_icache_cleanup_req"),
178           r_icache_cleanup_line("r_icache_cleanup_line"),
179
180           r_vci_cmd_fsm("r_vci_cmd_fsm"),
181           r_vci_cmd_min("r_vci_cmd_min"),
182           r_vci_cmd_max("r_vci_cmd_max"),
183           r_vci_cmd_cpt("r_vci_cmd_cpt"),
184
185           r_vci_rsp_fsm("r_vci_rsp_fsm"),
186           r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
187           r_vci_rsp_data_error("r_vci_rsp_data_error"),
188           r_vci_rsp_cpt("r_vci_rsp_cpt"),
189
190           r_dcache_buf_unc_valid("r_dcache_buf_unc_valid"),
191           r_icache_buf_unc_valid("r_icache_buf_unc_valid"),
192
193           r_vci_tgt_fsm("r_vci_tgt_fsm"),
194           r_tgt_addr("r_tgt_addr"),
195           r_tgt_word("r_tgt_word"),
196           r_tgt_update("r_tgt_update"),
197           r_tgt_srcid("r_tgt_srcid"),
198           r_tgt_pktid("r_tgt_pktid"),
199           r_tgt_trdid("r_tgt_trdid"),
200           r_tgt_icache_req("r_tgt_icache_req"),
201           r_tgt_dcache_req("r_tgt_dcache_req"),
202
203           r_wbuf("r_wbuf", dcache_words ),
204           r_icache("icache", icache_ways, icache_sets, icache_words),
205           r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
206
207{
208    r_icache_miss_buf = new data_t[icache_words];
209    r_dcache_miss_buf = new data_t[dcache_words];
210    r_tgt_buf         = new data_t[dcache_words];
211    r_tgt_val         = new bool[dcache_words];
212
213    SC_METHOD(transition);
214    dont_initialize();
215    sensitive << p_clk.pos();
216 
217    SC_METHOD(genMoore);
218    dont_initialize();
219    sensitive << p_clk.neg();
220
221    typename iss_t::CacheInfo cache_info;
222    cache_info.has_mmu = false;
223    cache_info.icache_line_size = icache_words*sizeof(data_t);
224    cache_info.icache_assoc = icache_ways;
225    cache_info.icache_n_lines = icache_sets;
226    cache_info.dcache_line_size = dcache_words*sizeof(data_t);
227    cache_info.dcache_assoc = dcache_ways;
228    cache_info.dcache_n_lines = dcache_sets;
229    m_iss.setCacheInfo(cache_info);
230} // end constructor
231
232///////////////////////////////////
233tmpl(/**/)::~VciCcXcacheWrapper()
234           ///////////////////////////////////
235{
236    delete [] r_icache_miss_buf;
237    delete [] r_dcache_miss_buf;
238    delete [] r_tgt_val;
239    delete [] r_tgt_buf;
240}
241
242////////////////////////
243tmpl(void)::print_cpi()
244           ////////////////////////
245{
246    std::cout << "CPU " << m_srcid << " : CPI = "
247              << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
248}
249////////////////////////
250tmpl(void)::print_stats()
251           ////////////////////////
252{
253    float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
254    std::cout << "------------------------------------" << std:: dec << std::endl;
255    std::cout << "CPU " << m_srcid << " / Time = " << m_cpt_total_cycles << std::endl;
256    std::cout << "- CPI                = " << (float)m_cpt_total_cycles/run_cycles << std::endl ;
257    std::cout << "- READ RATE          = " << (float)m_cpt_read/run_cycles << std::endl ;
258    std::cout << "- WRITE RATE         = " << (float)m_cpt_write/run_cycles << std::endl;
259    std::cout << "- UNCACHED READ RATE = " << (float)m_cpt_unc_read/m_cpt_read << std::endl ;
260    std::cout << "- CACHED WRITE RATE  = " << (float)m_cpt_write_cached/m_cpt_write << std::endl ;
261    std::cout << "- IMISS_RATE         = " << (float)m_cpt_ins_miss/run_cycles << std::endl;
262    std::cout << "- DMISS RATE         = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl ;
263    std::cout << "- INS MISS COST      = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl;
264    std::cout << "- IMISS TRANSACTION  = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl;
265    std::cout << "- DMISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl;
266    std::cout << "- DMISS TRANSACTION  = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl;
267    std::cout << "- UNC COST           = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl;
268    std::cout << "- UNC TRANSACTION    = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl;
269    std::cout << "- WRITE COST         = " << (float)m_cost_write_frz/m_cpt_write << std::endl;
270    std::cout << "- WRITE TRANSACTION  = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl;
271    std::cout << "- WRITE LENGTH       = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl;
272}
273
274//////////////////////////
275tmpl(void)::transition()
276           //////////////////////////
277{
278    if ( ! p_resetn.read() ) {
279
280        m_iss.reset();
281
282        // FSM states
283        r_dcache_fsm = DCACHE_IDLE;
284        r_icache_fsm = ICACHE_IDLE;
285        r_vci_cmd_fsm = CMD_IDLE;
286        r_vci_rsp_fsm = RSP_IDLE;
287        r_vci_tgt_fsm = TGT_IDLE;
288
289        // write buffer & caches
290        r_wbuf.reset();
291        r_icache.reset();
292        r_dcache.reset();
293
294        // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI  FSMs
295        r_icache_miss_req    = false;
296        r_icache_unc_req     = false;
297        r_icache_cleanup_req = false;
298        r_dcache_miss_req    = false;
299        r_dcache_unc_req     = false;
300        r_dcache_write_req   = false;
301        r_dcache_cleanup_req = false;
302
303        // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
304        r_tgt_icache_req     = false;
305        r_tgt_dcache_req     = false;
306
307        // internal messages in DCACHE et ICACHE FSMs
308        r_icache_inval_rsp   = false;
309        r_dcache_inval_rsp   = false;
310
311        // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs
312        r_dcache_buf_unc_valid = false;
313        r_icache_buf_unc_valid = false;
314        r_vci_rsp_data_error   = false;
315        r_vci_rsp_ins_error    = false;
316
317        // activity counters
318        m_cpt_dcache_data_read  = 0;
319        m_cpt_dcache_data_write = 0;
320        m_cpt_dcache_dir_read  = 0;
321        m_cpt_dcache_dir_write = 0;
322        m_cpt_icache_data_read  = 0;
323        m_cpt_icache_data_write = 0;
324        m_cpt_icache_dir_read  = 0;
325        m_cpt_icache_dir_write = 0;
326
327        m_cpt_cc_update = 0;
328        m_cpt_cc_inval = 0;
329
330        m_cpt_frz_cycles = 0;
331        m_cpt_total_cycles = 0;
332
333        m_cpt_read = 0;
334        m_cpt_write = 0;
335        m_cpt_data_miss = 0;
336        m_cpt_ins_miss = 0;
337        m_cpt_unc_read = 0;
338        m_cpt_write_cached = 0;
339
340        m_cost_write_frz = 0;
341        m_cost_data_miss_frz = 0;
342        m_cost_unc_read_frz = 0;
343        m_cost_ins_miss_frz = 0;
344
345        m_cpt_imiss_transaction = 0;
346        m_cpt_dmiss_transaction = 0;
347        m_cpt_unc_transaction = 0;
348        m_cpt_write_transaction = 0;
349
350        m_cost_imiss_transaction = 0;
351        m_cost_dmiss_transaction = 0;
352        m_cost_unc_transaction = 0;
353        m_cost_write_transaction = 0;
354        m_length_write_transaction = 0;
355
356        return;
357    }
358
359#if DEBUG_CC_XCACHE_WRAPPER
360    std::cout << "--------------------------------------------" << std::endl;
361    std::cout << std::dec << "CC_XCACHE_WRAPPER " << m_srcid << " / Time = " << m_cpt_total_cycles << std::endl;
362    std::cout             << " tgt fsm    = " << tgt_fsm_state_str[r_vci_tgt_fsm] << std::endl
363                          << " dcache fsm = " << dcache_fsm_state_str[r_dcache_fsm] << std::endl
364                          << " icache fsm = " << icache_fsm_state_str[r_icache_fsm] << std::endl
365                          << " cmd fsm    = " << cmd_fsm_state_str[r_vci_cmd_fsm] << std::endl
366                          << " rsp fsm    = " << rsp_fsm_state_str[r_vci_rsp_fsm] << std::endl;
367#endif
368
369    m_cpt_total_cycles++;
370
371    /////////////////////////////////////////////////////////////////////
372    // The TGT_FSM controls the following ressources:
373    // - r_vci_tgt_fsm
374    // - r_tgt_buf[nwords]
375    // - r_tgt_val[nwords]
376    // - r_tgt_update
377    // - r_tgt_word
378    // - r_tgt_addr
379    // - r_tgt_srcid
380    // - r_tgt_trdid
381    // - r_tgt_pktid
382    // All VCI commands must be CMD_WRITE.
383    // If the VCI address offset is null, the command is an invalidate
384    // request. It is an update request otherwise.
385    // The VCI_TGT FSM stores the external request arguments in the
386    // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req
387    // & r_tgt_dcache_req flip-flops to signal the external request to
388    // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
389    // of the update or invalidate request in the RSP state.
390    // -  for an invalidate request the VCI packet length is 1 word.
391    // The WDATA field contains the line index (i.e. the Z & Y fields).
392    // -  for an update request the VCI packet length is (n+2) words.
393    // The WDATA field of the first VCI word contains the line number.
394    // The WDATA field of the second VCI word contains the word index.
395    // The WDATA field of the n following words contains the values.
396    // -  for both invalidate & update requests, the VCI response
397    // is one single word.
398    // In case of errors in the VCI command packet, the simulation
399    // is stopped with an error message.
400    /////////////////////////////////////////////////////////////////////
401   
402    switch(r_vci_tgt_fsm) {
403
404    case TGT_IDLE:
405        if ( p_vci_tgt.cmdval.read() )
406        {
407            addr_t address = p_vci_tgt.address.read();
408
409            if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE)
410            {
411                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
412                std::cout << "the received VCI command is not a write" << std::endl;
413                exit(0);
414            }
415
416            // multi-update or multi-invalidate for data type
417            if ( (address != 0x3) && (! m_segment.contains(address)) )
418            {
419                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
420                std::cout << "out of segment VCI command received for a multi-updt or multi-inval request" << std::endl;
421                exit(0);
422            }
423
424            r_tgt_srcid = p_vci_tgt.srcid.read();
425            r_tgt_trdid = p_vci_tgt.trdid.read();
426            r_tgt_pktid = p_vci_tgt.pktid.read();
427            r_tgt_plen  = p_vci_tgt.plen.read();    // todo: wait L2 modification
428            r_tgt_addr = (addr_t)p_vci_tgt.wdata.read() * m_dcache_words * 4;
429           
430            if ( address == 0x3 )   // broadcast invalidate for data or instruction type
431            {
432                if ( ! p_vci_tgt.eop.read() )
433                {
434                    std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
435                    std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
436                    exit(0);
437                }
438                r_tgt_update = false;
439                r_vci_tgt_fsm = TGT_REQ_BROADCAST;
440                m_cpt_cc_inval++ ;
441            }
442            else                    // multi-update or multi-invalidate for data type
443            {
444                addr_t cell = address - m_segment.baseAddress();
445                if (cell == 0)
446                {                               // invalidate
447                    if ( ! p_vci_tgt.eop.read() )
448                    {
449                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
450                        std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
451                        exit(0);
452                    }
453                    r_tgt_update = false;
454                    r_vci_tgt_fsm = TGT_REQ_DCACHE;
455                    m_cpt_cc_inval++ ;
456                }
457                else
458                {                                // update
459                    if ( p_vci_tgt.eop.read() )
460                    {
461                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
462                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
463                        exit(0);
464                    }
465                    r_tgt_update = true;
466                    r_vci_tgt_fsm = TGT_UPDT_WORD;
467                    m_cpt_cc_update++ ;
468                }
469            } // end if address
470        } // end if cmdval
471        break;
472
473    case TGT_UPDT_WORD:
474        if (p_vci_tgt.cmdval.read())
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 MULTI-UPDATE command length must be N+2 words" << std::endl;
480                exit(0);
481            }
482            for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_val[i] = false;
483            r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
484            r_vci_tgt_fsm = TGT_UPDT_DATA;
485        }
486        break;
487
488    case TGT_UPDT_DATA:
489        if (p_vci_tgt.cmdval.read())
490        {
491            size_t word = r_tgt_word.read();
492            if ( word >= m_dcache_words )
493            {
494                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
495                std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
496                exit(0);
497            }
498            r_tgt_buf[word] = p_vci_tgt.wdata.read();
499            if(p_vci_tgt.be.read())    r_tgt_val[word] = true;
500            r_tgt_word = word + 1;
501            if (p_vci_tgt.eop.read())  r_vci_tgt_fsm = TGT_REQ_DCACHE;
502        }
503        break;
504
505    case TGT_REQ_BROADCAST:
506        if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
507        {
508            r_vci_tgt_fsm = TGT_RSP_BROADCAST;
509            r_tgt_icache_req = true;
510            r_tgt_dcache_req = true;
511        }
512        break;
513
514    case TGT_REQ_DCACHE:
515        if ( !r_tgt_dcache_req.read() )
516        {
517            r_vci_tgt_fsm = TGT_RSP_DCACHE;
518            r_tgt_dcache_req = true;
519        }
520        break;
521
522    case TGT_RSP_BROADCAST:
523        if ( p_vci_tgt.rspack.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
524        {
525            // one response
526            if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
527            {
528                r_vci_tgt_fsm = TGT_IDLE;
529                r_tgt_icache_rsp = false;
530                r_tgt_dcache_rsp = false;
531            }
532
533            // if data and instruction have the inval line, need two responses 
534            if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
535            {
536                r_tgt_icache_rsp = false; // only reset one for respond the second time
537            }
538        }
539        break;
540
541    case TGT_RSP_DCACHE:
542        if ( p_vci_tgt.rspack.read() && !r_tgt_dcache_req.read() )
543        {
544            r_vci_tgt_fsm = TGT_IDLE;
545            r_tgt_dcache_rsp = false;
546        }
547        break;
548
549    } // end switch TGT_FSM
550
551    /////////////////////////////////////////////////////////////////////
552    // The ICACHE FSM controls the following ressources:
553    // - r_icache_fsm
554    // - r_icache_fsm_save
555    // - r_icache instruction cache access
556    // - r_icache_addr_save
557    // - r_icache_miss_req set
558    // - r_icache_unc_req set
559    // - r_icache_buf_unc_valid set
560    // - r_vci_rsp_ins_error reset
561    // - r_tgt_icache_req reset
562    // - ireq & irsp structures for communication with the processor
563    //
564    // 1/ External requests (update or invalidate) have highest priority.
565    //    They are taken into account in the IDLE and WAIT states.
566    //    As external hit should be extremly rare on the ICACHE,
567    //    all external requests are handled as invalidate...
568    //    In case of external request the ICACHE FSM goes to the CC_CHECK
569    //    state to test the external hit, and returns in the
570    //    pre-empted state after completion.
571    // 2/ Processor requests are taken into account only in the IDLE state.
572    //    In case of MISS, or in case of uncached instruction, the FSM
573    //    writes the missing address line in the  r_icache_addr_save register
574    //    and sets the r_icache_miss_req or the r_icache_unc_req flip-flops.
575    //    These request flip-flops are reset by the VCI_RSP FSM
576    //    when the VCI transaction is completed and the r_icache_buf_unc_valid
577    //    is set in case of uncached access.
578    //    In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
579    //    flip-flop. It is reset by the ICACHE FSM.
580    ///////////////////////////////////////////////////////////////////////
581
582    typename iss_t::InstructionRequest  ireq = ISS_IREQ_INITIALIZER;
583    typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
584
585    typename iss_t::DataRequest  dreq = ISS_DREQ_INITIALIZER;
586    typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
587
588    m_iss.getRequests( ireq, dreq );
589
590#if DEBUG_CC_XCACHE_WRAPPER
591    std::cout << " Instruction Request: " << ireq << std::endl;
592#endif
593
594    switch(r_icache_fsm) {
595        /////////////////
596    case ICACHE_IDLE:
597        {
598            if ( r_tgt_icache_req ) {   // external request
599                if ( ireq.valid ) m_cost_ins_miss_frz++;
600                r_icache_fsm = ICACHE_CC_INVAL;
601                r_icache_fsm_save = r_icache_fsm;
602                break;
603            }
604            if ( ireq.valid ) {
605                data_t  icache_ins = 0;
606                bool    icache_hit = false;
607                bool    icache_cached = m_cacheability_table[ireq.addr];
608                // icache_hit & icache_ins evaluation
609                if ( icache_cached ) {
610                    icache_hit = r_icache.read(ireq.addr, &icache_ins);
611                } else {
612                    icache_hit = ( r_icache_buf_unc_valid && (ireq.addr == r_icache_addr_save) );
613                    icache_ins = r_icache_miss_buf[0];
614                }
615                if ( ! icache_hit ) {
616                    m_cpt_ins_miss++;
617                    m_cost_ins_miss_frz++;
618                    r_icache_addr_save = ireq.addr;
619                    if ( icache_cached ) {
620                        r_icache_fsm = ICACHE_MISS_WAIT;
621                        r_icache_miss_req = true;
622                    } else {
623                        r_icache_fsm = ICACHE_UNC_WAIT;
624                        r_icache_unc_req = true;
625                    }
626                } else {
627                    r_icache_buf_unc_valid = false;
628                }
629                m_cpt_icache_dir_read += m_icache_ways;
630                m_cpt_icache_data_read += m_icache_ways;
631                irsp.valid          = icache_hit;
632                irsp.instruction    = icache_ins;
633            }
634            break;
635        }
636        //////////////////////
637    case ICACHE_MISS_WAIT:
638        {
639            m_cost_ins_miss_frz++;
640            if ( r_tgt_icache_req ) {   // external request
641                r_icache_fsm = ICACHE_CC_INVAL;
642                r_icache_fsm_save = r_icache_fsm;
643                break;
644            }
645            if ( !r_icache_miss_req && !r_icache_inval_rsp ) { // Miss read response and no invalidation
646                if ( r_vci_rsp_ins_error ) {
647                    r_icache_fsm = ICACHE_ERROR;
648                } else {
649                    r_icache_fsm = ICACHE_MISS_UPDT;
650                }
651            }
652            if ( !r_icache_miss_req && r_icache_inval_rsp ) { // Miss read response and invalidation
653                if ( r_vci_rsp_ins_error ) {
654                    r_icache_inval_rsp = false;
655                    r_icache_fsm = ICACHE_ERROR;
656                } else {
657                    r_icache_inval_rsp = false;
658                    r_icache_fsm = ICACHE_IDLE;
659                }
660            }
661            break;
662        }
663        /////////////////////
664    case ICACHE_UNC_WAIT:
665        {
666            m_cost_ins_miss_frz++;
667            if ( r_tgt_icache_req ) {   // external request
668                r_icache_fsm = ICACHE_CC_INVAL;
669                r_icache_fsm_save = r_icache_fsm;
670                break;
671            }
672            if ( !r_icache_unc_req ) {
673                if ( r_vci_rsp_ins_error ) {
674                    r_icache_fsm = ICACHE_ERROR;
675                } else {
676                    r_icache_fsm = ICACHE_IDLE;
677                    r_icache_buf_unc_valid = true;
678                }
679            }
680            break;
681        }
682        //////////////////
683    case ICACHE_ERROR:
684        {
685            r_icache_fsm = ICACHE_IDLE;
686            r_vci_rsp_ins_error = false;
687            irsp.error          = true;
688            irsp.valid          = true;
689            break;
690        }
691        //////////////////////
692    case ICACHE_MISS_UPDT:
693        {
694            if ( r_tgt_icache_req ) {   // external request
695                r_icache_fsm = ICACHE_CC_INVAL;
696                r_icache_fsm_save = r_icache_fsm;
697                break;
698            }
699            if(!r_icache_cleanup_req.read() && !r_icache_inval_rsp){
700                addr_t    ad  = r_icache_addr_save;
701                data_t*   buf = r_icache_miss_buf;
702                data_t    victim_index = 0;
703                m_cpt_icache_dir_write++;
704                m_cpt_icache_data_write++;
705                if ( ireq.valid ) m_cost_ins_miss_frz++;
706
707                r_icache_cleanup_req = r_icache.update(ad, buf, &victim_index);
708                r_icache_cleanup_line = victim_index;
709
710                r_icache_fsm        = ICACHE_IDLE;
711                break;
712            }
713            if(r_icache_inval_rsp){
714                if ( ireq.valid ) m_cost_ins_miss_frz++;
715                r_icache_inval_rsp  = false;
716                r_icache_fsm        = ICACHE_IDLE;
717                break;
718            }
719            if ( ireq.valid ) m_cost_ins_miss_frz++;
720        }
721        /////////////////////
722    case ICACHE_CC_INVAL: 
723        {                       
724            addr_t    ad  = r_tgt_addr;
725            if ( ireq.valid ) m_cost_ins_miss_frz++;
726            m_cpt_icache_dir_read += m_icache_ways;
727            if( (( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT )) &&
728                ((r_icache_addr_save.read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1))) ) {
729                r_icache_inval_rsp = true;
730            } else {
731                r_tgt_icache_rsp = r_icache.inval(ad);
732            }
733            r_tgt_icache_req = false;
734            r_icache_fsm = r_icache_fsm_save;
735            break;
736        }
737
738    } // end switch r_icache_fsm
739
740#if DEBUG_CC_XCACHE_WRAPPER
741    std::cout << " Instruction Response: " << irsp << std::endl;
742#endif
743
744    //////////////////////////////////////////////////////////////////////://///////////
745    // The DCACHE FSM controls the following ressources:
746    // - r_dcache_fsm
747    // - r_dcache_fsm_save
748    // - r_dcache (data cache access)
749    // - r_dcache_addr_save
750    // - r_dcache_wdata_save
751    // - r_dcache_rdata_save
752    // - r_dcache_type_save
753    // - r_dcache_be_save
754    // - r_dcache_cached_save
755    // - r_dcache_miss_req set
756    // - r_dcache_unc_req set
757    // - r_dcache_write_req set
758    // - r_dcache_cleanup_req set
759    // - r_vci_rsp_data_error reset
760    // - r_tgt_dcache_req reset
761    // - r_wbuf write
762    // - dreq & drsp structures for communication with the processor
763    //
764    // 1/ EXTERNAL REQUEST :
765    //    There is an external request when the tgt_dcache req flip-flop is set,
766    //    requesting a line invalidation or a line update.
767    //    External requests are taken into account in the states  IDLE, WRITE_REQ, 
768    //    UNC_WAIT, MISS_WAIT, and have the highest priority :
769    //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
770    //    goes to the CC_CHECK state to execute the requested action, and returns to the
771    //    pre-empted state.
772    //  2/ PROCESSOR REQUEST :
773    //   In order to support VCI write burst, the processor requests are taken into account
774    //   in the WRITE_REQ state as well as in the IDLE state.
775    //   - In the IDLE state, the processor request cannot be satisfied if
776    //   there is a cached read miss, or an uncached read.
777    //   - In the WRITE_REQ state, the request cannot be satisfied if
778    //   there is a cached read miss, or an uncached read,
779    //   or when the write buffer is full.
780    //   - In all other states, the processor request is not satisfied.
781    //
782    //   The cache access takes into account the cacheability_table.
783    //   In case of processor request, there is five conditions to exit the IDLE state:
784    //   - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal),
785    //     then to the MISS_UPDT state, and finally to the IDLE state.
786    //   - UNCACHED READ  => to the UNC_WAIT state (waiting the r_miss_ok signal),
787    //     and to the IDLE state.
788    //   - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state.
789    //   - WRITE MISS => directly to the WRITE_REQ state to access the write buffer.
790    //   - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state.
791    //
792    // Error handling :  Read Bus Errors are synchronous events, but
793    // Write Bus Errors are asynchronous events (processor is not frozen).
794    // - If a Read Bus Error is detected, the VCI_RSP FSM sets the
795    //   r_vci_rsp_data_error flip-flop, and the synchronous error is signaled
796    //   by the DCACHE FSM.
797    // - If a Write Bus Error is detected, the VCI_RSP FSM  signals
798    //   the asynchronous error using the setWriteBerr() method.
799    ///////////////////////////////////////////////////////////////////////////////////
800
801#if DEBUG_CC_XCACHE_WRAPPER
802    std::cout << " Data Request: " << dreq << std::endl;
803#endif
804
805    //if( (m_cpt_total_cycles % 10000) ==0 ) std::cout << std::dec << "Proc " << m_srcid << " Data Request: " << dreq << std::endl;
806
807    switch ( r_dcache_fsm ) {
808
809        /////////////////////
810    case DCACHE_WRITE_REQ:
811        {
812            if ( r_tgt_dcache_req ) {   // external request
813                r_dcache_fsm = DCACHE_CC_CHECK;
814                r_dcache_fsm_save = r_dcache_fsm;
815                break;
816            }
817
818            // try to post the write request in the write buffer
819            if ( !r_dcache_write_req ) {    // no previous write transaction     
820                if ( r_wbuf.wok(r_dcache_addr_save) ) {   // write request in the same cache line
821                    r_wbuf.write(r_dcache_addr_save, r_dcache_be_save, r_dcache_wdata_save);
822                    // close the write packet if uncached
823                    if ( !r_dcache_cached_save ) r_dcache_write_req = true ;
824                } else {   
825                    // close the write packet if write request not in the same cache line
826                    r_dcache_write_req = true; 
827                    m_cost_write_frz++;
828                    break;  // posting request not possible : stay in DCACHE_WRITEREQ state
829                }
830            } else {    //  previous write transaction not completed
831                m_cost_write_frz++;
832                break;  // posting request not possible : stay in DCACHE_WRITEREQ state 
833            }
834
835            // close the write packet if the next processor request is not a write
836            if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE) ) r_dcache_write_req = true ;
837
838            // The next state and the processor request parameters are computed
839            // as in the DCACHE_IDLE state (see below ...)
840        }
841        /////////////////
842    case DCACHE_IDLE:
843        {
844            if ( r_tgt_dcache_req ) {   // external request
845                r_dcache_fsm = DCACHE_CC_CHECK;
846                r_dcache_fsm_save = r_dcache_fsm;
847                break;
848            }
849
850            if ( dreq.valid ) {             
851                bool        dcache_hit     = false;
852                data_t      dcache_rdata   = 0;
853                bool        dcache_cached;
854                m_cpt_dcache_data_read += m_dcache_ways;
855                m_cpt_dcache_dir_read += m_dcache_ways;
856
857                // dcache_cached evaluation
858                switch (dreq.type) {
859                case iss_t::DATA_LL:
860                case iss_t::DATA_SC:
861                case iss_t::XTN_READ:
862                case iss_t::XTN_WRITE:
863                    dcache_cached = false;
864                    break;
865                default:
866                    dcache_cached = m_cacheability_table[dreq.addr];
867                }
868
869                // dcache_hit & dcache_rdata evaluation
870                if ( dcache_cached ) {
871                    dcache_hit = r_dcache.read(dreq.addr, &dcache_rdata);
872                } else {
873                    dcache_hit = ( !r_dcache_unc_req && (dreq.addr == r_dcache_addr_save) );
874                    dcache_rdata = r_dcache_miss_buf[0];
875                }
876
877                switch( dreq.type ) {
878                case iss_t::DATA_READ:
879                case iss_t::DATA_LL:
880                case iss_t::DATA_SC:
881                    m_cpt_read++;
882                    if ( dcache_hit ) {
883                        r_dcache_fsm = DCACHE_IDLE;
884                        drsp.valid = true;
885                        drsp.rdata = dcache_rdata;
886                        r_dcache_buf_unc_valid = false;
887                    } else {
888                        if ( dcache_cached ) {
889                            m_cpt_data_miss++;
890                            m_cost_data_miss_frz++;
891                            r_dcache_miss_req = true;
892                            r_dcache_fsm = DCACHE_MISS_WAIT;
893                        } else {
894                            m_cpt_unc_read++;
895                            m_cost_unc_read_frz++;
896                            r_dcache_unc_req = true;
897                            r_dcache_fsm = DCACHE_UNC_WAIT;
898                        }
899                    }
900                    break;
901                case iss_t::XTN_READ:
902                case iss_t::XTN_WRITE:
903                    // only DCACHE INVALIDATE request are supported
904                    if ( dreq.addr/4 == iss_t::XTN_DCACHE_INVAL )
905                        r_dcache_fsm = DCACHE_INVAL;
906                    drsp.valid = true;
907                    drsp.rdata = 0;
908                    break;
909                case iss_t::DATA_WRITE:
910                    m_cpt_write++;
911                    if ( dcache_hit && dcache_cached ) {
912                        r_dcache_fsm = DCACHE_WRITE_UPDT;
913                        m_cpt_write_cached++;
914                    } else {
915                        r_dcache_fsm = DCACHE_WRITE_REQ;
916                    }
917                    drsp.valid = true;
918                    drsp.rdata = 0;
919                    break;
920                } // end switch dreq.type
921
922                r_dcache_addr_save      = dreq.addr;
923                r_dcache_type_save      = dreq.type;
924                r_dcache_wdata_save     = dreq.wdata;
925                r_dcache_be_save        = dreq.be;
926                r_dcache_rdata_save     = dcache_rdata;
927                r_dcache_cached_save    = dcache_cached;
928
929            } else {    // end if dreq.valid
930                r_dcache_fsm = DCACHE_IDLE;
931            }
932            // processor request are not accepted in the WRITE_REQUEST state
933            // when the write buffer is not writeable
934            if ( (r_dcache_fsm == DCACHE_WRITE_REQ) &&
935                 (r_dcache_write_req || !r_wbuf.wok(r_dcache_addr_save)) ) {
936                drsp.valid = false;
937                drsp.rdata = 0;
938            }
939            break;
940        }
941        ///////////////////////
942    case DCACHE_WRITE_UPDT:
943        {
944            m_cpt_dcache_data_write++;
945            data_t mask = vci_param::be2mask(r_dcache_be_save);
946            data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
947            r_dcache.write(r_dcache_addr_save, wdata);
948            r_dcache_fsm = DCACHE_WRITE_REQ;
949            break;
950        }
951        //////////////////////
952    case DCACHE_MISS_WAIT:
953        {
954            if ( dreq.valid ) m_cost_data_miss_frz++;
955            if ( r_tgt_dcache_req.read() ) {   // external request
956                r_dcache_fsm = DCACHE_CC_CHECK;
957                r_dcache_fsm_save = r_dcache_fsm;
958                break;
959            }
960            if ( !r_dcache_miss_req && !r_dcache_inval_rsp ) { // Miss read response and no invalidation
961                if ( r_vci_rsp_data_error ) {
962                    r_dcache_fsm = DCACHE_ERROR;
963                } else {
964                    r_dcache_fsm = DCACHE_MISS_UPDT;
965                }
966                break;
967            }
968            if ( !r_dcache_miss_req && r_dcache_inval_rsp ) { // Miss read response and invalidation
969                if ( r_vci_rsp_data_error ) {
970                    r_dcache_inval_rsp  = false;
971                    r_dcache_fsm = DCACHE_ERROR;
972                } else {
973                    r_dcache_inval_rsp  = false;
974                    r_dcache_fsm = DCACHE_IDLE;
975                }
976                break;
977            }
978            break;
979        }
980        //////////////////////
981    case DCACHE_MISS_UPDT:
982        {
983            if ( r_tgt_dcache_req.read() ) {   // external request
984                r_dcache_fsm = DCACHE_CC_CHECK;
985                r_dcache_fsm_save = r_dcache_fsm;
986                break;
987            }
988            if( !r_dcache_cleanup_req.read() && !r_dcache_inval_rsp ){
989                addr_t  ad  = r_dcache_addr_save;
990                data_t* buf = new data_t[m_dcache_words];
991                for(size_t i=0; i<m_dcache_words; i++) {
992                    buf[i] = r_dcache_miss_buf[i];
993                }
994                data_t  victim_index = 0;
995                if ( dreq.valid ) m_cost_data_miss_frz++;
996                m_cpt_dcache_data_write++;
997                m_cpt_dcache_dir_write++;
998
999                r_dcache_cleanup_req = r_dcache.update(ad, buf, &victim_index);
1000                r_dcache_cleanup_line = victim_index;
1001           
1002                r_dcache_fsm = DCACHE_IDLE;
1003                delete [] buf;
1004                break;
1005            }
1006            if( r_dcache_inval_rsp ){
1007                r_dcache_inval_rsp  = false;
1008                r_dcache_fsm = DCACHE_IDLE;
1009                break;
1010            }
1011            break;
1012        }
1013        ////////////////////
1014    case DCACHE_UNC_WAIT:
1015        {
1016            if ( dreq.valid ) m_cost_unc_read_frz++;
1017            if ( r_tgt_dcache_req ) {   // external request
1018                r_dcache_fsm = DCACHE_CC_CHECK;
1019                r_dcache_fsm_save = r_dcache_fsm;
1020                break;
1021            }
1022            if ( !r_dcache_unc_req ) {
1023                if ( r_vci_rsp_data_error ) {
1024                    r_dcache_fsm = DCACHE_ERROR;
1025                } else {
1026                    r_dcache_fsm = DCACHE_IDLE;
1027                        // If request was a DATA_SC we need to invalidate the corresponding cache line,
1028                        // so that subsequent access to this line are read from RAM
1029                        if (dreq.type == iss_t::DATA_SC) {
1030                            r_dcache_fsm = DCACHE_INVAL;
1031                            r_dcache_wdata_save = r_dcache_addr_save;
1032                        }
1033                    r_dcache_buf_unc_valid = true;
1034                }
1035            }
1036            break;
1037        }
1038        //////////////////
1039    case DCACHE_ERROR:
1040        {
1041            r_dcache_fsm = DCACHE_IDLE;
1042            r_vci_rsp_data_error = false;
1043            drsp.error = true;
1044            drsp.valid = true;
1045            break;
1046        }
1047        /////////////////   
1048    case DCACHE_INVAL:
1049        {
1050            m_cpt_dcache_dir_read += m_dcache_ways;
1051            r_dcache.inval(r_dcache_addr_save);
1052            r_dcache_fsm = DCACHE_IDLE;
1053            break;
1054        }
1055        /////////////////////
1056    case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
1057        {
1058            m_cpt_dcache_dir_read += m_dcache_ways;
1059            m_cpt_dcache_data_read += m_dcache_ways;
1060            addr_t  ad           = r_tgt_addr;
1061            data_t  dcache_rdata = 0;
1062
1063            if(( ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) &&
1064               ( (r_dcache_addr_save.read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) {
1065                r_dcache_inval_rsp = true;
1066                r_tgt_dcache_req = false;
1067                r_dcache_fsm = r_dcache_fsm_save;
1068            } else {
1069                bool    dcache_hit   = r_dcache.read(ad, &dcache_rdata);
1070                if ( dcache_hit && r_tgt_update ) {
1071                    r_dcache_fsm = DCACHE_CC_UPDT;
1072                    // complete the line buffer in case of update
1073                    for ( size_t word = 0 ; word < m_dcache_words ; word++ ) {
1074                        if ( !r_tgt_val[word] ) {
1075                            addr_t  ad = r_tgt_addr + (addr_t)word;
1076                            r_dcache.read(ad, &dcache_rdata);
1077                            r_tgt_buf[word] = dcache_rdata;
1078                        }
1079                    }
1080                } else if ( dcache_hit && !r_tgt_update ) {
1081                    r_dcache_fsm = DCACHE_CC_INVAL;
1082                } else {
1083                    r_dcache_fsm = DCACHE_CC_NOP;
1084                }
1085            }
1086            break;
1087        }
1088        ///////////////////
1089    case DCACHE_CC_UPDT:    // update directory and data cache       
1090        {
1091            m_cpt_dcache_dir_write++;
1092            m_cpt_dcache_data_write++;
1093            addr_t  ad      = r_tgt_addr;
1094            data_t* buf     = r_tgt_buf;
1095            for(size_t i=0; i<m_dcache_words; i++){
1096                if(r_tgt_val[i]) r_dcache.write( ad + i*4, buf[i]);
1097            }
1098            r_tgt_dcache_req = false;
1099            r_dcache_fsm = r_dcache_fsm_save;
1100            break;
1101        }
1102        /////////////////////
1103    case DCACHE_CC_INVAL:   // invalidate a cache line
1104        {
1105            addr_t  ad      = r_tgt_addr;
1106            r_tgt_dcache_rsp = r_dcache.inval(ad);
1107            r_tgt_dcache_req = false;
1108            r_dcache_fsm = r_dcache_fsm_save;
1109            break;
1110        }
1111        ///////////////////
1112    case DCACHE_CC_NOP:     // no external hit
1113        {
1114            r_tgt_dcache_req = false;
1115            r_dcache_fsm = r_dcache_fsm_save;
1116            break;
1117        }   
1118    } // end switch r_dcache_fsm
1119
1120#if DEBUG_CC_XCACHE_WRAPPER
1121    std::cout << " Data Response: " << drsp << std::endl;
1122#endif
1123
1124    /////////// execute one iss cycle /////////////////////////////////////////////
1125    {
1126        uint32_t it = 0;
1127        for (size_t i=0; i<(size_t)iss_t::n_irq; i++)
1128            if(p_irq[i].read()) it |= (1<<i);
1129        m_iss.executeNCycles(1, irsp, drsp, it);
1130    }
1131
1132    if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) ) m_cpt_frz_cycles++;
1133   
1134
1135    ////////////////////////////////////////////////////////////////////////////
1136    // The VCI_CMD FSM controls the following ressources:
1137    // - r_vci_cmd_fsm
1138    // - r_vci_cmd_min
1139    // - r_vci_cmd_max
1140    // - r_vci_cmd_cpt
1141    // - wbuf reset
1142    //
1143    // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
1144    // There is 7 request types, with the following priorities :
1145    // 1 - Instruction Miss     : r_icache_miss_req
1146    // 2 - Data Write           : r_dcache_write_req
1147    // 3 - Data Read Miss       : r_dcache_miss_req
1148    // 4 - Data Read Uncached   : r_dcache_unc_req
1149    // 5 - Instruction Cleanup  : r_icache_cleanup_req
1150    // 6 - Data Cleanup         : r_dcache_cleanup_req
1151    // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM
1152    // and RSP_FSM exit simultaneously the IDLE state.
1153    //
1154    // VCI formats:
1155    // According to the VCI advanced specification, all read requests packets
1156    // (read Uncached, Miss data, Miss instruction) are one word packets.
1157    // For write burst packets, all words must be in the same cache line,
1158    // and addresses must be contiguous (the BE field is 0 in case of "holes").
1159    //////////////////////////////////////////////////////////////////////////////
1160
1161    switch (r_vci_cmd_fsm) {
1162   
1163    case CMD_IDLE:
1164        if (r_vci_rsp_fsm != RSP_IDLE) break;
1165
1166        r_vci_cmd_cpt = 0;
1167        if ( r_icache_miss_req ) {
1168            r_vci_cmd_fsm = CMD_INS_MISS;
1169            m_cpt_imiss_transaction++;
1170        } else if ( r_icache_unc_req ) {
1171            r_vci_cmd_fsm = CMD_INS_UNC;
1172            m_cpt_imiss_transaction++;
1173        } else if ( r_dcache_write_req ) {
1174            r_vci_cmd_fsm = CMD_DATA_WRITE;
1175            r_vci_cmd_cpt = r_wbuf.getMin();
1176            r_vci_cmd_min = r_wbuf.getMin();
1177            r_vci_cmd_max = r_wbuf.getMax();
1178            m_cpt_write_transaction++;
1179            m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1);
1180        } else if ( r_dcache_miss_req ) {
1181            r_vci_cmd_fsm = CMD_DATA_MISS;
1182            m_cpt_dmiss_transaction++;
1183        } else if ( r_dcache_unc_req ) {
1184            r_vci_cmd_fsm = CMD_DATA_UNC;
1185            m_cpt_unc_transaction++;
1186        } else if ( r_icache_cleanup_req ) {
1187            r_vci_cmd_fsm = CMD_INS_CLEANUP;
1188        } else if ( r_dcache_cleanup_req ) {
1189            r_vci_cmd_fsm = CMD_DATA_CLEANUP;
1190        }
1191        break;
1192           
1193    case CMD_DATA_WRITE:
1194        if ( p_vci_ini.cmdack.read() ) {
1195            r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
1196            if (r_vci_cmd_cpt == r_vci_cmd_max) {
1197                r_vci_cmd_fsm = CMD_IDLE ;
1198                r_wbuf.reset() ;
1199            }
1200        }
1201        break;
1202
1203    case CMD_INS_MISS:
1204    case CMD_INS_UNC:
1205    case CMD_DATA_MISS:
1206    case CMD_DATA_UNC:
1207    case CMD_INS_CLEANUP:
1208    case CMD_DATA_CLEANUP:
1209        if ( p_vci_ini.cmdack.read() ) {
1210            r_vci_cmd_fsm = CMD_IDLE;
1211        }
1212        break;
1213
1214    } // end  switch r_vci_cmd_fsm
1215
1216    //////////////////////////////////////////////////////////////////////////
1217    // The VCI_RSP FSM controls the following ressources:
1218    // - r_vci_rsp_fsm:
1219    // - r_icache_miss_buf[m_icache_words]
1220    // - r_dcache_miss_buf[m_dcache_words]
1221    // - r_icache_miss_req reset
1222    // - r_icache_unc_req reset
1223    // - r_dcache_miss_req reset
1224    // - r_icache_cleanup_req reset
1225    // - r_dcache_cleanup_req reset
1226    // - r_vci_rsp_data_error set
1227    // - r_vci_rsp_ins_error set
1228    // - r_vci_rsp_cpt
1229    // In order to have only one active VCI transaction, this VCI_RSP_FSM
1230    // is synchronized with the VCI_CMD FSM, and both FSMs exit the
1231    // IDLE state simultaneously.
1232    //
1233    // VCI formats:
1234    // This component accepts single word or multi-word response packets for
1235    // write response packets.
1236    //
1237    // Error handling:
1238    // This FSM analyzes the VCI error code and signals directly the
1239    // Write Bus Error.
1240    // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error
1241    // flip_flop and the error is signaled by the DCACHE FSM. 
1242    // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
1243    // flip_flop and the error is signaled by the DCACHE FSM. 
1244    // In case of Cleanup Error, the simulation stops with an error message...
1245    //////////////////////////////////////////////////////////////////////////
1246
1247    switch (r_vci_rsp_fsm) {
1248
1249    case RSP_IDLE:
1250        if(p_vci_ini.rspval.read())
1251            {
1252                std::cout << "CC_XCache " << m_srcid << " Unexpected response" << std::endl;
1253            }
1254        assert( ! p_vci_ini.rspval.read() && "Unexpected response" );
1255        if (r_vci_cmd_fsm != CMD_IDLE) break;
1256
1257        r_vci_rsp_cpt = 0;
1258        if      ( r_icache_miss_req )       r_vci_rsp_fsm = RSP_INS_MISS;
1259        else if ( r_icache_unc_req )        r_vci_rsp_fsm = RSP_DATA_WRITE;
1260        else if ( r_dcache_write_req )      r_vci_rsp_fsm = RSP_DATA_WRITE;
1261        else if ( r_dcache_miss_req )       r_vci_rsp_fsm = RSP_DATA_MISS;
1262        else if ( r_dcache_unc_req )        r_vci_rsp_fsm = RSP_DATA_UNC;
1263        else if ( r_icache_cleanup_req )    r_vci_rsp_fsm = RSP_INS_CLEANUP;
1264        else if ( r_dcache_cleanup_req )    r_vci_rsp_fsm = RSP_DATA_CLEANUP;
1265        break;
1266
1267    case RSP_INS_MISS:
1268        m_cost_imiss_transaction++;
1269        if ( ! p_vci_ini.rspval.read() )
1270            break;
1271        assert( (r_vci_rsp_cpt < m_icache_words) &&
1272                "The VCI response packet for instruction miss is too long" );
1273        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
1274        r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini.rdata.read();
1275
1276        if ( p_vci_ini.reop.read() ) {
1277            assert( (r_vci_rsp_cpt == m_icache_words - 1) &&
1278                    "The VCI response packet for instruction miss is too short");
1279            r_icache_miss_req = false;
1280            r_vci_rsp_fsm = RSP_IDLE;
1281        }
1282        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
1283        break;
1284
1285    case RSP_INS_UNC:
1286        m_cost_imiss_transaction++;
1287        if ( ! p_vci_ini.rspval.read() )
1288            break;
1289        assert(p_vci_ini.reop.read() &&
1290               "illegal VCI response packet for uncached instruction");
1291        r_icache_miss_buf[0] = (data_t)p_vci_ini.rdata.read();
1292        r_vci_rsp_fsm = RSP_IDLE;
1293        r_icache_unc_req = false;
1294        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
1295        break;
1296
1297    case RSP_DATA_MISS:
1298        m_cost_dmiss_transaction++;
1299        if ( ! p_vci_ini.rspval.read() )
1300            break;
1301        assert(r_vci_rsp_cpt != m_dcache_words &&
1302               "illegal VCI response packet for data read miss");
1303        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
1304        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini.rdata.read();
1305        if ( p_vci_ini.reop.read() ) {
1306            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
1307                   "illegal VCI response packet for data read miss");
1308            r_dcache_miss_req = false;
1309            r_vci_rsp_fsm = RSP_IDLE;
1310        }
1311        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
1312        break;
1313
1314    case RSP_DATA_WRITE:
1315        m_cost_write_transaction++;
1316        if ( ! p_vci_ini.rspval.read() )
1317            break;
1318        if ( p_vci_ini.reop.read() ) {
1319            r_vci_rsp_fsm = RSP_IDLE;
1320            r_dcache_write_req = false;
1321        }
1322        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) m_iss.setWriteBerr();
1323        break;
1324
1325    case RSP_DATA_UNC:
1326        m_cost_unc_transaction++;
1327        if ( ! p_vci_ini.rspval.read() )
1328            break;
1329        assert(p_vci_ini.reop.read() &&
1330               "illegal VCI response packet for data read uncached");
1331        r_dcache_miss_buf[0] = (data_t)p_vci_ini.rdata.read();
1332        r_vci_rsp_fsm = RSP_IDLE;
1333        r_dcache_unc_req = false;
1334        if ( p_vci_ini.rerror.read() != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
1335        break;
1336
1337    case RSP_INS_CLEANUP:
1338    case RSP_DATA_CLEANUP:
1339        if ( ! p_vci_ini.rspval.read() )
1340            break;
1341        assert( p_vci_ini.reop.read() &&
1342                "illegal VCI response packet for icache cleanup");
1343        assert( (p_vci_ini.rerror.read() == vci_param::ERR_NORMAL) &&
1344                "error in response packet for icache cleanup");
1345        if ( r_vci_rsp_fsm == RSP_INS_CLEANUP ) r_icache_cleanup_req = false;
1346        else                                    r_dcache_cleanup_req = false;
1347        r_vci_rsp_fsm = RSP_IDLE;
1348        break;
1349       
1350    } // end switch r_vci_rsp_fsm
1351
1352} // end transition()
1353
1354//////////////////////////////////////////////////////////////////////////////////
1355tmpl(void)::genMoore()
1356           //////////////////////////////////////////////////////////////////////////////////
1357{
1358    // VCI initiator response
1359
1360    p_vci_ini.rspack = true;
1361
1362    // VCI initiator command
1363
1364    switch (r_vci_cmd_fsm.read() ) {
1365
1366    case CMD_IDLE:
1367        p_vci_ini.cmdval  = false;
1368        p_vci_ini.address = 0;
1369        p_vci_ini.wdata   = 0;
1370        p_vci_ini.be      = 0;
1371        p_vci_ini.plen    = 0;
1372        p_vci_ini.cmd     = vci_param::CMD_NOP;
1373        p_vci_ini.trdid   = 0;
1374        p_vci_ini.pktid   = 0;
1375        p_vci_ini.srcid   = 0;
1376        p_vci_ini.cons    = false;
1377        p_vci_ini.wrap    = false;
1378        p_vci_ini.contig  = false;
1379        p_vci_ini.clen    = 0;
1380        p_vci_ini.cfixed  = false;
1381        p_vci_ini.eop     = false;
1382        break;
1383
1384    case CMD_DATA_UNC:
1385        p_vci_ini.cmdval = true;
1386        p_vci_ini.address = r_dcache_addr_save & ~0x3;
1387        switch( r_dcache_type_save ) {
1388        case iss_t::DATA_READ:
1389            p_vci_ini.wdata = 0;
1390            p_vci_ini.be  = r_dcache_be_save.read();
1391            p_vci_ini.cmd = vci_param::CMD_READ;
1392            break;
1393        case iss_t::DATA_LL:
1394            p_vci_ini.wdata = 0;
1395            p_vci_ini.be  = 0xF;
1396            p_vci_ini.cmd = vci_param::CMD_LOCKED_READ;
1397            break;
1398        case iss_t::DATA_SC:
1399            p_vci_ini.wdata = r_dcache_wdata_save.read();
1400            p_vci_ini.be  = 0xF;
1401            p_vci_ini.cmd = vci_param::CMD_STORE_COND;
1402            break;
1403        default:
1404            assert("this should not happen");
1405        }
1406        p_vci_ini.plen = 4;
1407        p_vci_ini.trdid  = 0;   // data cache uncached read
1408        p_vci_ini.pktid  = 0;
1409        p_vci_ini.srcid  = m_srcid;
1410        p_vci_ini.cons   = false;
1411        p_vci_ini.wrap   = false;
1412        p_vci_ini.contig = true;
1413        p_vci_ini.clen   = 0;
1414        p_vci_ini.cfixed = false;
1415        p_vci_ini.eop    = true;
1416        break;
1417
1418    case CMD_DATA_WRITE:
1419        p_vci_ini.cmdval  = true;
1420        p_vci_ini.address = r_wbuf.getAddress(r_vci_cmd_cpt);
1421        p_vci_ini.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
1422        p_vci_ini.be      = r_wbuf.getBe(r_vci_cmd_cpt);
1423        p_vci_ini.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
1424        p_vci_ini.cmd     = vci_param::CMD_WRITE;
1425        p_vci_ini.trdid   = 0;  // data cache write
1426        p_vci_ini.pktid   = 0;
1427        p_vci_ini.srcid   = m_srcid;
1428        p_vci_ini.cons    = false;
1429        p_vci_ini.wrap    = false;
1430        p_vci_ini.contig  = true;
1431        p_vci_ini.clen    = 0;
1432        p_vci_ini.cfixed  = false;
1433        p_vci_ini.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
1434        break;
1435
1436    case CMD_DATA_MISS:
1437        p_vci_ini.cmdval = true;
1438        p_vci_ini.address = r_dcache_addr_save & m_dcache_yzmask;
1439        p_vci_ini.be     = 0xF;
1440        p_vci_ini.plen   = m_dcache_words << 2;
1441        p_vci_ini.cmd    = vci_param::CMD_READ;
1442        p_vci_ini.trdid  = 1;   // data cache cached read
1443        p_vci_ini.pktid  = 0;
1444        p_vci_ini.srcid  = m_srcid;
1445        p_vci_ini.cons   = false;
1446        p_vci_ini.wrap   = false;
1447        p_vci_ini.contig = true;
1448        p_vci_ini.clen   = 0;
1449        p_vci_ini.cfixed = false;
1450        p_vci_ini.eop = true;
1451        break;
1452
1453    case CMD_INS_MISS:
1454        p_vci_ini.cmdval = true;
1455        p_vci_ini.address = r_icache_addr_save & m_icache_yzmask;
1456        p_vci_ini.be     = 0xF;
1457        p_vci_ini.plen   = m_icache_words << 2;
1458        p_vci_ini.cmd    = vci_param::CMD_READ;
1459        p_vci_ini.trdid  = 3;   // ins cache cached read
1460        p_vci_ini.pktid  = 0;
1461        p_vci_ini.srcid  = m_srcid;
1462        p_vci_ini.cons   = false;
1463        p_vci_ini.wrap   = false;
1464        p_vci_ini.contig = true;
1465        p_vci_ini.clen   = 0;
1466        p_vci_ini.cfixed = false;
1467        p_vci_ini.eop = true;
1468        break;
1469
1470    case CMD_INS_UNC:
1471        p_vci_ini.cmdval = true;
1472        p_vci_ini.address = r_icache_addr_save & ~0x3;
1473        p_vci_ini.be     = 0xF;
1474        p_vci_ini.plen   = 4;
1475        p_vci_ini.cmd    = vci_param::CMD_READ;
1476        p_vci_ini.trdid  = 2;   // ins cache uncached read
1477        p_vci_ini.pktid  = 0;
1478        p_vci_ini.srcid  = m_srcid;
1479        p_vci_ini.cons   = false;
1480        p_vci_ini.wrap   = false;
1481        p_vci_ini.contig = true;
1482        p_vci_ini.clen   = 0;
1483        p_vci_ini.cfixed = false;
1484        p_vci_ini.eop = true;
1485        break;
1486
1487    case CMD_INS_CLEANUP:
1488    case CMD_DATA_CLEANUP:
1489        p_vci_ini.cmdval = true;
1490        if ( r_vci_cmd_fsm == CMD_INS_CLEANUP ) p_vci_ini.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
1491        else                                    p_vci_ini.address = r_dcache_cleanup_line.read() * (m_icache_words<<2);
1492        p_vci_ini.wdata  = 0;
1493        p_vci_ini.be     = 0;
1494        p_vci_ini.plen   = 4;
1495        p_vci_ini.cmd    = vci_param::CMD_WRITE;
1496        p_vci_ini.trdid  = 1; // cleanup for distinguish from a write
1497        p_vci_ini.pktid  = 0;
1498        p_vci_ini.srcid  = m_srcid;
1499        p_vci_ini.cons   = false;
1500        p_vci_ini.wrap   = false;
1501        p_vci_ini.contig = false;
1502        p_vci_ini.clen   = 0;
1503        p_vci_ini.cfixed = false;
1504        p_vci_ini.eop = true;
1505        break;
1506
1507    } // end switch r_vci_cmd_fsm
1508
1509    // VCI_TGT
1510
1511    switch ( r_vci_tgt_fsm.read() ) {
1512
1513    case TGT_IDLE:
1514    case TGT_UPDT_WORD:
1515    case TGT_UPDT_DATA:
1516        p_vci_tgt.cmdack  = true;
1517        p_vci_tgt.rspval  = false;
1518        break;
1519
1520    case TGT_RSP_BROADCAST:
1521        p_vci_tgt.cmdack  = false;
1522        p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
1523        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
1524        p_vci_tgt.rpktid  = r_tgt_pktid.read();
1525        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
1526        p_vci_tgt.rdata   = 0;
1527        p_vci_tgt.rerror  = 0;
1528        p_vci_tgt.reop    = true;
1529        break;
1530
1531    case TGT_RSP_DCACHE:
1532        p_vci_tgt.cmdack  = false;
1533        p_vci_tgt.rspval  = !r_tgt_dcache_req.read();
1534        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
1535        p_vci_tgt.rpktid  = r_tgt_pktid.read();
1536        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
1537        p_vci_tgt.rdata   = 0;
1538        p_vci_tgt.rerror  = 0;
1539        p_vci_tgt.reop    = true;
1540        break;
1541
1542    case TGT_REQ_BROADCAST:
1543    case TGT_REQ_DCACHE:
1544        p_vci_tgt.cmdack  = false;
1545        p_vci_tgt.rspval  = false;
1546        break;
1547
1548    } // end switch TGT_FSM
1549} // end genMoore()
1550
1551}} // end namespace
1552
1553// Local Variables:
1554// tab-width: 4
1555// c-basic-offset: 4
1556// c-file-offsets:((innamespace . 0)(inline-open . 0))
1557// indent-tabs-mode: nil
1558// End:
1559
1560// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1561
1562
1563
1564
Note: See TracBrowser for help on using the repository browser.