source: trunk/modules/vci_cc_xcache_wrapper_multi/caba/source/src/vci_cc_xcache_wrapper_multi.cpp @ 47

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