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

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

Import TSAR modules in TSAR's own svn

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