source: trunk/modules/vci_io_bridge/caba/source/src/vci_io_bridge.cpp

Last change on this file was 1022, checked in by cfuguet, 9 years ago

Fixing warning with new compiler's versions.

File size: 108.2 KB
RevLine 
[434]1/* -*- c++ -*-
[240]2 * File : vci_io_bridge.cpp
3 * Copyright (c) UPMC, Lip6, SoC
[434]4 * Authors: Cassio Fraga, Alain Greiner
[240]5 *
6 * SOCLIB_LGPL_HEADER_BEGIN
[715]7 *
[240]8 * This file is part of SoCLib, GNU LGPLv2.1.
[715]9 *
[240]10 * SoCLib is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; version 2.1 of the License.
[715]13 *
[240]14 * SoCLib is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
[715]18 *
[240]19 * You should have received a copy of the GNU Lesser General Public
20 * License along with SoCLib; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
[715]23 *
[240]24 * SOCLIB_LGPL_HEADER_END
[984]25 *
26 * Maintainers: Cesar Fuguet Tortolero <cesar.fuguet-tortolero@lip6.fr>
[240]27 */
28
29#include <cassert>
30#include "arithmetics.h"
31#include "alloc_elems.h"
32#include "../include/vci_io_bridge.h"
33
[434]34
[240]35//////   debug services   ///////////////////////////////////////////////////////
36// All debug messages are conditionned by two variables:
37// - compile time : DEBUG_*** : defined below
38// - execution time : m_debug_***  : defined by constructor arguments
[434]39//    m_debug_activated = (m_debug_ok) and (m_cpt_cycle > m_debug_start_cycle)
[240]40/////////////////////////////////////////////////////////////////////////////////
41
[715]42#define DEBUG_DMA_CMD           1
43#define DEBUG_DMA_RSP           1
44#define DEBUG_TLB_MISS          1
45#define DEBUG_CONFIG_CMD        1
46#define DEBUG_CONFIG_RSP        1
47#define DEBUG_MISS_WTI_CMD      1
[240]48
[715]49namespace soclib {
[240]50namespace caba {
51
52namespace {
53
[715]54const char *dma_cmd_fsm_state_str[] =
[434]55    {
[240]56        "DMA_CMD_IDLE",
[712]57        "DMA_CMD_DMA_REQ",
58        "DMA_CMD_WTI_IOX_REQ",
59        "DMA_CMD_ERR_WAIT_EOP",
60        "DMA_CMD_ERR_WTI_REQ",
61        "DMA_CMD_ERR_RSP_REQ",
62        "DMA_CMD_TLB_MISS_WAIT",
[240]63    };
64
[715]65const char *dma_rsp_fsm_state_str[] =
[434]66    {
[712]67        "DMA_RSP_IDLE_DMA",
68        "DMA_RSP_IDLE_WTI",
69        "DMA_RSP_IDLE_ERR",
70        "DMA_RSP_PUT_DMA",
71        "DMA_RSP_PUT_WTI",
72        "DMA_RSP_PUT_ERR",
[240]73    };
74
[715]75const char *tlb_fsm_state_str[] =
[434]76    {
77        "TLB_IDLE",
78        "TLB_MISS",
79        "TLB_PTE1_GET",
80        "TLB_PTE1_SELECT",
81        "TLB_PTE1_UPDT",
[715]82        "TLB_PTE2_GET",
[434]83        "TLB_PTE2_SELECT",
84        "TLB_PTE2_UPDT",
85        "TLB_WAIT",
86        "TLB_RETURN",
87        "TLB_INVAL_CHECK",
[240]88    };
89
[715]90const char *config_cmd_fsm_state_str[] =
[434]91    {
[240]92        "CONFIG_CMD_IDLE",
[720]93        "CONFIG_CMD_WAIT",
[715]94        "CONFIG_CMD_HI",
95        "CONFIG_CMD_LO",
[585]96        "CONFIG_CMD_PUT",
97        "CONFIG_CMD_RSP",
[240]98    };
99
[715]100const char *config_rsp_fsm_state_str[] =
[434]101    {
[712]102        "CONFIG_RSP_IDLE_IOX",
103        "CONFIG_RSP_IDLE_LOC",
[715]104        "CONFIG_RSP_PUT_LO",
105        "CONFIG_RSP_PUT_HI",
106        "CONFIG_RSP_PUT_UNC",
107        "CONFIG_RSP_PUT_LOC",
[240]108    };
109
[715]110const char *miss_wti_rsp_state_str[] =
111    {
[549]112        "MISS_WTI_RSP_IDLE",
[712]113        "MISS_WTI_RSP_WTI_IOX",
114        "MISS_WTI_RSP_WTI_MMU",
[434]115        "MISS_WTI_RSP_MISS",
[240]116    };
117}
118
[984]119#define tmpl(...)  template<typename vci_param_int,typename vci_param_ext> \
120    __VA_ARGS__ VciIoBridge<vci_param_int,vci_param_ext>
[240]121
[434]122////////////////////////
[240]123tmpl(/**/)::VciIoBridge(
[715]124    sc_module_name                      name,
125    const soclib::common::MappingTable  &mt_ext,
126    const soclib::common::MappingTable  &mt_int,
127    const soclib::common::MappingTable  &mt_iox,
128    const soclib::common::IntTab        &int_tgtid,     // INT network TGTID
129    const soclib::common::IntTab        &int_srcid,     // INT network SRCID
130    const soclib::common::IntTab        &iox_tgtid,     // IOX network TGTID
131    const soclib::common::IntTab        &iox_srcid,     // IOX network SRCID
[434]132    const size_t                        dcache_words,
[715]133    const size_t                        iotlb_ways,
134    const size_t                        iotlb_sets,
135    const uint32_t                      debug_start_cycle,
136    const bool                          debug_ok)
[240]137    : soclib::caba::BaseModule(name),
138
[434]139      p_clk("p_clk"),
140      p_resetn("p_resetn"),
141      p_vci_ini_ram("p_vci_ini_ram"),
142      p_vci_tgt_iox("p_vci_tgt_iox"),
143      p_vci_ini_iox("p_vci_ini_iox"),
144      p_vci_tgt_int("p_vci_tgt_int"),
145      p_vci_ini_int("p_vci_ini_int"),
[240]146
[434]147      m_words( dcache_words ),
[240]148
[434]149      // INT & IOX Network
150      m_int_seglist( mt_int.getSegmentList( int_tgtid )),
[715]151      m_int_srcid( mt_int.indexForId( int_srcid )),
[434]152      m_iox_seglist( mt_iox.getSegmentList( iox_tgtid )),
[715]153      m_iox_srcid( mt_iox.indexForId( iox_srcid )),
[434]154
[715]155      m_srcid_gid_mask( mt_int.getSrcidLevelBits()[0],  // use global bits
156                        mt_int.getSrcidLevelBits()[1]), // drop local bits
157      m_srcid_lid_mask( mt_int.getSrcidLevelBits()[1],  // use local bits
158                        0),
159
[240]160      m_iotlb_ways(iotlb_ways),
161      m_iotlb_sets(iotlb_sets),
162
163      m_debug_start_cycle(debug_start_cycle),
164      m_debug_ok(debug_ok),
165
[434]166      // addressable registers
[240]167      r_iommu_ptpr("r_iommu_ptpr"),
168      r_iommu_active("r_iommu_active"),
169      r_iommu_bvar("r_iommu_bvar"),
170      r_iommu_etr("r_iommu_etr"),
171      r_iommu_bad_id("r_iommu_bad_id"),
[712]172      r_iommu_wti_enable("r_iommu_wti_enable"),
173      r_iommu_wti_addr_lo("r_iommu_wti_addr_lo"),
[240]174
[434]175      // DMA_CMD FSM registers
[240]176      r_dma_cmd_fsm("r_dma_cmd_fsm"),
[434]177      r_dma_cmd_paddr("r_dma_cmd_paddr"),
[240]178
[712]179      r_dma_cmd_to_miss_wti_cmd_req("r_dma_cmd_to_miss_wti_cmd_req"),
180      r_dma_cmd_to_miss_wti_cmd_addr("r_dma_cmd_to_miss_wti_cmd_addr"),
181      r_dma_cmd_to_miss_wti_cmd_srcid("r_dma_cmd_to_miss_wti_cmd_srcid"),
182      r_dma_cmd_to_miss_wti_cmd_trdid("r_dma_cmd_to_miss_wti_cmd_trdid"),
183      r_dma_cmd_to_miss_wti_cmd_pktid("r_dma_cmd_to_miss_wti_cmd_pktid"),
184      r_dma_cmd_to_miss_wti_cmd_wdata("r_dma_cmd_to_miss_wti_cmd_wdata"),
185
186      r_dma_cmd_to_dma_rsp_req("r_dma_cmd_to_dma_rsp_req"),
187      r_dma_cmd_to_dma_rsp_rsrcid("r_dma_cmd_to_dma_rsp_rsrcid"),
188      r_dma_cmd_to_dma_rsp_rtrdid("r_dma_cmd_to_dma_rsp_rtrdid"),
189      r_dma_cmd_to_dma_rsp_rpktid("r_dma_cmd_to_dma_rsp_rpktid"),
[715]190
[712]191      r_dma_cmd_to_tlb_req("r_dma_cmd_to_tlb_req"),
192      r_dma_cmd_to_tlb_vaddr("r_dma_cmd_to_tlb_vaddr"),
[715]193
[434]194      //DMA_RSP FSM registers
195      r_dma_rsp_fsm("r_dma_rsp_fsm"),
[240]196
[715]197      // CONFIG_CMD FSM registers
[434]198      r_config_cmd_fsm("r_config_cmd_fsm"),
[712]199
200      r_config_cmd_to_tlb_req("r_config_cmd_to_tlb_req"),
201      r_config_cmd_to_tlb_vaddr("r_config_cmd_to_tlb_vaddr"),
202
203      r_config_cmd_to_config_rsp_req("r_config_cmd_to_config_rsp_req"),
204      r_config_cmd_to_config_rsp_rerror("r_config_cmd_to_config_rsp_rerror"),
205      r_config_cmd_to_config_rsp_rdata("r_config_cmd_to_config_rsp_rdata"),
[715]206      r_config_cmd_to_config_rsp_rsrcid("r_config_cmd_to_config_rsp_rsrcid"),
207      r_config_cmd_to_config_rsp_rtrdid("r_config_cmd_to_config_rsp_rtrdid"),
208      r_config_cmd_to_config_rsp_rpktid("r_config_cmd_to_config_rsp_rpktid"),
[712]209
[585]210      r_config_cmd_wdata("r_config_cmd_wdata"),
211      r_config_cmd_be("r_config_cmd_be"),
[952]212      r_config_cmd_cmd("r_config_cmd_cmd"),
[585]213      r_config_cmd_address("r_config_cmd_address"),
214      r_config_cmd_srcid("r_config_cmd_srcid"),
[715]215      r_config_cmd_trdid("r_config_cmd_trdid"),
[585]216      r_config_cmd_pktid("r_config_cmd_pktid"),
217      r_config_cmd_plen("r_config_cmd_plen"),
218      r_config_cmd_clen("r_config_cmd_clen"),
219      r_config_cmd_cons("r_config_cmd_cons"),
220      r_config_cmd_contig("r_config_cmd_contig"),
221      r_config_cmd_cfixed("r_config_cmd_cfixed"),
222      r_config_cmd_wrap("r_config_cmd_wrap"),
223      r_config_cmd_eop("r_config_cmd_eop"),
[240]224
[715]225      // ID translation table used by CONFIG_CMD and CONFIG_RSP FSMs
226      m_iox_transaction_tab(1),
227
228      // CONFIG_RSP FSM registers
[434]229      r_config_rsp_fsm("r_config_rsp_fsm"),
[715]230      r_config_rsp_rsrcid("r_config_rsp_rsrcid"),
231      r_config_rsp_rtrdid("r_config_rsp_rtrdid"),
[434]232
233      // TLB FSM registers
234      r_tlb_fsm("r_tlb_fsm"),
[240]235      r_waiting_transaction("r_waiting_transaction"),
236      r_tlb_miss_type("r_tlb_miss_type"),
[434]237      r_tlb_miss_error("r_tlb_miss_error"),
[712]238
[715]239      r_tlb_paddr("r_tlb_paddr"),
[434]240      r_tlb_pte_flags("r_tlb_pte_flags"),
241      r_tlb_pte_ppn("r_tlb_pte_ppn"),
242      r_tlb_way("r_tlb_way"),
[715]243      r_tlb_set("r_tlb_set"),
244
[434]245      r_tlb_buf_valid("r_tlb_buf_valid"),
246      r_tlb_buf_tag("r_tlb_buf_tag"),
247      r_tlb_buf_vaddr("r_tlb_buf_vaddr"),
248      r_tlb_buf_big_page("r_tlb_buf_big_page"),
[240]249
[712]250      r_tlb_to_miss_wti_cmd_req("r_tlb_to_miss_wti_cmd_req"),
[240]251
[712]252      // MISS_WTI_RSP FSM registers
[715]253      r_miss_wti_rsp_fsm("r_miss_wti_rsp_fsm"),
[712]254      r_miss_wti_rsp_error_wti("r_miss_wti_rsp_error_wti"),
255      r_miss_wti_rsp_error_miss("r_miss_wti_rsp_error_miss"),
256      r_miss_wti_rsp_count("r_miss_wti_rsp_count"),
[434]257
[712]258      r_miss_wti_rsp_to_dma_rsp_req("r_miss_wti_rsp_to_dma_rsp_req"),
259      r_miss_wti_rsp_to_dma_rsp_rerror("r_miss_wti_rsp_to_dma_rsp_rerror"),
260      r_miss_wti_rsp_to_dma_rsp_rsrcid("r_miss_wti_rsp_to_dma_rsp_rsrcid"),
261      r_miss_wti_rsp_to_dma_rsp_rtrdid("r_miss_wti_rsp_to_dma_rsp_rtrdid"),
262      r_miss_wti_rsp_to_dma_rsp_rpktid("r_miss_wti_rsp_to_dma_rsp_rpktid"),
[434]263
[984]264      r_miss_wti_rsp_to_tlb_done("r_miss_wti_rsp_to_tlb_done"),
265
[434]266      // TLB for IOMMU
267      r_iotlb("iotlb", 0, iotlb_ways, iotlb_sets, vci_param_int::N),
[715]268
[434]269      // DMA_CMD FIFOs
270      m_dma_cmd_addr_fifo("m_dma_cmd_addr_fifo",2),
[715]271      m_dma_cmd_srcid_fifo("m_dma_cmd_srcid_fifo",2),
272      m_dma_cmd_trdid_fifo("m_dma_cmd_trdid_fifo",2),
273      m_dma_cmd_pktid_fifo("m_dma_cmd_pktid_fifo",2),
274      m_dma_cmd_be_fifo("m_dma_cmd_be_fifo",2),
275      m_dma_cmd_cmd_fifo("m_dma_cmd_cmd_fifo",2),
276      m_dma_cmd_contig_fifo("m_dma_cmd_contig_fifo",2),
277      m_dma_cmd_data_fifo("m_dma_cmd_data_fifo",2),
[434]278      m_dma_cmd_eop_fifo("m_dma_cmd_eop_fifo",2),
[715]279      m_dma_cmd_cons_fifo("m_dma_cmd_cons_fifo",2),
280      m_dma_cmd_plen_fifo("m_dma_cmd_plen_fifo",2),
281      m_dma_cmd_wrap_fifo("m_dma_cmd_wrap_fifo",2),
[434]282      m_dma_cmd_cfixed_fifo("m_dma_cmd_cfixed_fifo",2),
[715]283      m_dma_cmd_clen_fifo("m_dma_cmd_clen_fifo",2),
[240]284
[434]285      // DMA_RSP FIFOs
286      m_dma_rsp_data_fifo("m_dma_rsp_data_fifo",2),
287      m_dma_rsp_rsrcid_fifo("m_dma_rsp_rsrcid_fifo",2),
288      m_dma_rsp_rtrdid_fifo("m_dma_rsp_rtrdid_fifo",2),
289      m_dma_rsp_rpktid_fifo("m_dma_rsp_rpktid_fifo",2),
290      m_dma_rsp_reop_fifo("m_dma_rsp_reop_fifo",2),
291      m_dma_rsp_rerror_fifo("m_dma_rsp_rerror_fifo",2),
[715]292
[434]293      // CONFIG_CMD FIFOs
294      m_config_cmd_addr_fifo("m_config_cmd_addr_fifo",2),
295      m_config_cmd_srcid_fifo("m_config_cmd_srcid_fifo",2),
296      m_config_cmd_trdid_fifo("m_config_cmd_trdid_fifo",2),
297      m_config_cmd_pktid_fifo("m_config_cmd_pktid_fifo",2),
298      m_config_cmd_be_fifo("m_config_cmd_be_fifo",2),
299      m_config_cmd_cmd_fifo("m_config_cmd_cmd_fifo",2),
300      m_config_cmd_contig_fifo("m_config_cmd_contig_fifo",2),
301      m_config_cmd_data_fifo("m_config_cmd_data_fifo",2),
302      m_config_cmd_eop_fifo("m_config_cmd_eop_fifo",2),
303      m_config_cmd_cons_fifo("m_config_cmd_cons_fifo",2),
304      m_config_cmd_plen_fifo("m_config_cmd_plen_fifo",2),
305      m_config_cmd_wrap_fifo("m_config_cmd_wrap_fifo",2),
306      m_config_cmd_cfixed_fifo("m_config_cmd_cfixed_fifo",2),
307      m_config_cmd_clen_fifo("m_config_cmd_clen_fifo",2),
308
309      // CONFIG_RSP FIFOs
[715]310      m_config_rsp_data_fifo("m_config_rsp_data_fifo",2),
[434]311      m_config_rsp_rsrcid_fifo("m_config_rsp_rsrcid_fifo",2),
312      m_config_rsp_rtrdid_fifo("m_config_rsp_rtrdid_fifo",2),
313      m_config_rsp_rpktid_fifo("m_config_rsp_rpktid_fifo",2),
314      m_config_rsp_reop_fifo("m_config_rsp_reop_fifo",2),
[712]315      m_config_rsp_rerror_fifo("m_config_rsp_rerror_fifo",2),
316
317      // MISS_WTI_CMD FIFOs
318      m_miss_wti_cmd_addr_fifo("m_miss_wti_cmd_addr_fifo",2),
319      m_miss_wti_cmd_srcid_fifo("m_miss_wti_cmd_srcid_fifo",2),
320      m_miss_wti_cmd_trdid_fifo("m_miss_wti_cmd_trdid_fifo",2),
321      m_miss_wti_cmd_pktid_fifo("m_miss_wti_cmd_pktid_fifo",2),
322      m_miss_wti_cmd_be_fifo("m_miss_wti_cmd_be_fifo",2),
323      m_miss_wti_cmd_cmd_fifo("m_miss_wti_cmd_cmd_fifo",2),
324      m_miss_wti_cmd_contig_fifo("m_miss_wti_cmd_contig_fifo",2),
325      m_miss_wti_cmd_data_fifo("m_miss_wti_cmd_data_fifo",2),
326      m_miss_wti_cmd_eop_fifo("m_miss_wti_cmd_eop_fifo",2),
327      m_miss_wti_cmd_cons_fifo("m_miss_wti_cmd_cons_fifo",2),
328      m_miss_wti_cmd_plen_fifo("m_miss_wti_cmd_plen_fifo",2),
329      m_miss_wti_cmd_wrap_fifo("m_miss_wti_cmd_wrap_fifo",2),
330      m_miss_wti_cmd_cfixed_fifo("m_miss_wti_cmd_cfixed_fifo",2),
331      m_miss_wti_cmd_clen_fifo("m_miss_wti_cmd_clen_fifo",2)
[240]332{
[434]333    std::cout << "  - Building VciIoBridge : " << name << std::endl;
334
[715]335    // checking segments on INT network
[434]336    assert ( ( not m_int_seglist.empty() ) and
337    "VCI_IO_BRIDGE ERROR : no segment allocated on INT network");
338
339    std::list<soclib::common::Segment>::iterator int_seg;
340    for ( int_seg = m_int_seglist.begin() ; int_seg != m_int_seglist.end() ; int_seg++ )
341    {
342        std::cout << "    => segment " << int_seg->name()
343                  << " / base = " << std::hex << int_seg->baseAddress()
[715]344                  << " / size = " << int_seg->size()
345                  << " / special = " << int_seg->special() << std::endl;
[434]346    }
347
[715]348    // checking segments on IOX network
[434]349    assert ( ( not m_iox_seglist.empty() ) and
350    "VCI_IO_BRIDGE ERROR : no segment allocated on IOX network");
351
352    std::list<soclib::common::Segment>::iterator iox_seg;
353    for ( iox_seg = m_iox_seglist.begin() ; iox_seg != m_iox_seglist.end() ; iox_seg++ )
354    {
355        std::cout << "    => segment " << iox_seg->name()
356                  << " / base = " << std::hex << iox_seg->baseAddress()
[715]357                  << " / size = " << iox_seg->size() << std::endl;
[434]358    }
359
[715]360    assert( (vci_param_int::N == vci_param_ext::N) and
[434]361    "VCI_IO_BRIDGE ERROR: VCI ADDRESS widths must be equal on the 3 networks");
362
363    assert( (vci_param_int::N <=  64) and
364    "VCI_IO_BRIDGE ERROR: VCI ADDRESS width cannot be bigger than 64 bits");
365
[585]366    assert( (vci_param_int::B == 4) and
[715]367    "VCI_IO_BRIDGE ERROR: VCI DATA width must be 32 bits on internal network");
[434]368
[585]369    assert( (vci_param_ext::B == 8) and
[715]370    "VCI_IO_BRIDGE ERROR: VCI DATA width must be 64 bits on external network");
[434]371
372    assert( (vci_param_int::S == vci_param_ext::S) and
373            "VCI_IO_BRIDGE ERROR: SRCID widths must be equal on the 3 networks");
374
375    // Cache line buffer
376    r_tlb_buf_data = new uint32_t[dcache_words];
377
[240]378    SC_METHOD(transition);
379    dont_initialize();
380    sensitive << p_clk.pos();
[715]381
[240]382    SC_METHOD(genMoore);
383    dont_initialize();
384    sensitive << p_clk.neg();
385
[1022]386}
[240]387
388/////////////////////////////////////
389tmpl(/**/)::~VciIoBridge()
390/////////////////////////////////////
391{
[434]392    delete [] r_tlb_buf_data;
[240]393}
394
395////////////////////////////////////
396tmpl(void)::print_trace(size_t mode)
397////////////////////////////////////
398{
[549]399    // b0 : IOTLB trace
[240]400
401    std::cout << std::dec << "IO_BRIDGE " << name() << std::endl;
402
[434]403    std::cout << "  "  << dma_cmd_fsm_state_str[r_dma_cmd_fsm.read()]
[240]404              << " | " << dma_rsp_fsm_state_str[r_dma_rsp_fsm.read()]
[434]405              << " | " << tlb_fsm_state_str[r_tlb_fsm.read()]
[240]406              << " | " << config_cmd_fsm_state_str[r_config_cmd_fsm.read()]
407              << " | " << config_rsp_fsm_state_str[r_config_rsp_fsm.read()]
[549]408              << " | " << miss_wti_rsp_state_str[r_miss_wti_rsp_fsm.read()]
[434]409              << std::endl;
[240]410
411    if(mode & 0x01)
412    {
413        std::cout << "  IOTLB" << std::endl;
414        r_iotlb.printTrace();
415    }
[715]416
417    if(mode & 0x02)
418    {
419        std::cout << "  IOX TRANSACTION TAB" << std::endl;
420        m_iox_transaction_tab.printTrace();
421    }
[240]422}
423
424////////////////////////
425tmpl(void)::print_stats()
426////////////////////////
427{
[715]428    std::cout << name()
429        << "\n- IOTLB MISS RATE                                = "
430        << (float)m_cpt_iotlb_miss/m_cpt_iotlb_read
431        << "\n- IOTLB MISS COST                                = "
432        << (float)m_cost_iotlb_miss/m_cpt_iotlb_miss
433        << "\n- IOTLB MISS TRANSACTION COST                    = "
434        << (float)m_cost_iotlbmiss_transaction/m_cpt_iotlbmiss_transaction
435        << "\n- IOTLB MISS TRANSACTION RATE (OVER ALL MISSES)  = "
436        << (float)m_cpt_iotlbmiss_transaction/m_cpt_iotlb_miss
437        << std::endl;
[240]438}
439
440////////////////////////
441tmpl(void)::clear_stats()
442////////////////////////
443{
[715]444    m_cpt_iotlb_read                = 0;
445    m_cpt_iotlb_miss                = 0;
[240]446    m_cost_iotlb_miss               = 0;
[715]447    m_cpt_iotlbmiss_transaction     = 0;
448    m_cost_iotlbmiss_transaction    = 0;
[240]449}
450
[712]451////////////////////////////////////
452tmpl(bool)::is_wti(vci_addr_t paddr)
453////////////////////////////////////
454{
[715]455    std::list<soclib::common::Segment>::iterator seg;
456    for ( seg  = m_iox_seglist.begin() ;
457          seg != m_iox_seglist.end()   ;
458          seg++ )
459    {
460        if ( seg->contains(paddr) ) return seg->special();
461    }
462    return false;
[712]463}
464
[240]465/////////////////////////
466tmpl(void)::transition()
467/////////////////////////
468{
[715]469    if ( not p_resetn.read() )
[240]470    {
[715]471        r_dma_cmd_fsm      = DMA_CMD_IDLE;
472        r_dma_rsp_fsm      = DMA_RSP_IDLE_DMA;
473        r_tlb_fsm          = TLB_IDLE;
[434]474        r_config_cmd_fsm   = CONFIG_CMD_IDLE;
[712]475        r_config_rsp_fsm   = CONFIG_RSP_IDLE_IOX;
[434]476        r_miss_wti_rsp_fsm = MISS_WTI_RSP_IDLE;
[240]477
[715]478        r_tlb_buf_valid    = false;
479        r_iommu_active     = false;
480        r_iommu_wti_enable = false;
[712]481
[715]482        // initializing translation table
483        m_iox_transaction_tab.init();
[712]484
[240]485        // initializing FIFOs
486        m_dma_cmd_addr_fifo.init();
487        m_dma_cmd_srcid_fifo.init();
488        m_dma_cmd_trdid_fifo.init();
489        m_dma_cmd_pktid_fifo.init();
490        m_dma_cmd_be_fifo.init();
491        m_dma_cmd_cmd_fifo.init();
492        m_dma_cmd_contig_fifo.init();
493        m_dma_cmd_data_fifo.init();
494        m_dma_cmd_eop_fifo.init();
495        m_dma_cmd_cons_fifo.init();
496        m_dma_cmd_plen_fifo.init();
497        m_dma_cmd_wrap_fifo.init();
498        m_dma_cmd_cfixed_fifo.init();
499        m_dma_cmd_clen_fifo.init();
[715]500
[240]501        m_dma_rsp_rsrcid_fifo.init();
502        m_dma_rsp_rtrdid_fifo.init();
503        m_dma_rsp_rpktid_fifo.init();
504        m_dma_rsp_data_fifo.init();
505        m_dma_rsp_rerror_fifo.init();
506        m_dma_rsp_reop_fifo.init();
[715]507
[240]508        m_config_cmd_addr_fifo.init();
509        m_config_cmd_srcid_fifo.init();
510        m_config_cmd_trdid_fifo.init();
511        m_config_cmd_pktid_fifo.init();
512        m_config_cmd_be_fifo.init();
513        m_config_cmd_cmd_fifo.init();
514        m_config_cmd_contig_fifo.init();
515        m_config_cmd_data_fifo.init();
516        m_config_cmd_eop_fifo.init();
517        m_config_cmd_cons_fifo.init();
518        m_config_cmd_plen_fifo.init();
519        m_config_cmd_wrap_fifo.init();
520        m_config_cmd_cfixed_fifo.init();
521        m_config_cmd_clen_fifo.init();
[715]522
[712]523        m_miss_wti_cmd_addr_fifo.init();
524        m_miss_wti_cmd_srcid_fifo.init();
525        m_miss_wti_cmd_trdid_fifo.init();
526        m_miss_wti_cmd_pktid_fifo.init();
527        m_miss_wti_cmd_be_fifo.init();
528        m_miss_wti_cmd_cmd_fifo.init();
529        m_miss_wti_cmd_contig_fifo.init();
530        m_miss_wti_cmd_data_fifo.init();
531        m_miss_wti_cmd_eop_fifo.init();
532        m_miss_wti_cmd_cons_fifo.init();
533        m_miss_wti_cmd_plen_fifo.init();
534        m_miss_wti_cmd_wrap_fifo.init();
535        m_miss_wti_cmd_cfixed_fifo.init();
536        m_miss_wti_cmd_clen_fifo.init();
[715]537
[240]538        m_config_rsp_rsrcid_fifo.init();
539        m_config_rsp_rtrdid_fifo.init();
540        m_config_rsp_rpktid_fifo.init();
541        m_config_rsp_data_fifo.init();
542        m_config_rsp_rerror_fifo.init();
543        m_config_rsp_reop_fifo.init();
[715]544
545        // SET/RESET Communication flip-flops
[712]546        r_dma_cmd_to_miss_wti_cmd_req  = false;
547        r_dma_cmd_to_dma_rsp_req       = false;
[715]548        r_dma_cmd_to_tlb_req           = false;
549        r_config_cmd_to_tlb_req        = false;
[712]550        r_config_cmd_to_config_rsp_req = false;
551        r_tlb_to_miss_wti_cmd_req      = false;
552        r_miss_wti_rsp_to_dma_rsp_req  = false;
[984]553        r_miss_wti_rsp_to_tlb_done     = false;
[240]554
[712]555        // error flip_flops
556        r_miss_wti_rsp_error_miss      = false;
557        r_miss_wti_rsp_error_wti       = false;
558
[434]559        // Debug variable
[715]560        m_debug_activated              = false;
561
562        // activity counters
563        m_cpt_total_cycles             = 0;
564        m_cpt_iotlb_read               = 0;
565        m_cpt_iotlb_miss               = 0;
566        m_cpt_iotlbmiss_transaction    = 0;
567        m_cost_iotlbmiss_transaction   = 0;
568
[712]569        m_cpt_trt_dma_full             = 0;
570        m_cpt_trt_dma_full_cost        = 0;
571        m_cpt_trt_config_full          = 0;
572        m_cpt_trt_config_full_cost     = 0;
[240]573
574        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_dma_cmd            [i]   = 0;
575        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_dma_rsp            [i]   = 0;
[434]576        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_tlb                [i]   = 0;
[240]577        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_config_cmd         [i]   = 0;
578        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_config_rsp         [i]   = 0;
[434]579        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_miss_wti_rsp       [i]   = 0;
580
[240]581        return;
582    }
583
[712]584    // default values for the 5 FIFOs
585    bool            dma_cmd_fifo_put          = false;
586    bool            dma_cmd_fifo_get          = p_vci_ini_ram.cmdack.read();
[715]587    vci_srcid_t     dma_cmd_fifo_srcid        = 0;
588
589    bool            dma_rsp_fifo_put          = false;
[712]590    bool            dma_rsp_fifo_get          = p_vci_tgt_iox.rspack.read();
591    vci_rerror_t    dma_rsp_fifo_rerror       = 0;
592    vci_srcid_t     dma_rsp_fifo_rsrcid       = 0;
593    vci_trdid_t     dma_rsp_fifo_rtrdid       = 0;
594    vci_pktid_t     dma_rsp_fifo_rpktid       = 0;
595    ext_data_t      dma_rsp_fifo_rdata        = 0;
596    bool            dma_rsp_fifo_reop         = false;
[240]597
[712]598    bool            config_cmd_fifo_put       = false;
599    bool            config_cmd_fifo_get       = p_vci_ini_iox.cmdack.read();
[434]600
[712]601    bool            config_rsp_fifo_put       = false;
602    bool            config_rsp_fifo_get       = p_vci_tgt_int.rspack.read();
603    vci_rerror_t    config_rsp_fifo_rerror    = 0;
604    vci_srcid_t     config_rsp_fifo_rsrcid    = 0;
605    vci_trdid_t     config_rsp_fifo_rtrdid    = 0;
606    vci_pktid_t     config_rsp_fifo_rpktid    = 0;
607    ext_data_t      config_rsp_fifo_rdata     = 0;
608    bool            config_rsp_fifo_reop      = false;
609
610    bool            miss_wti_cmd_fifo_put     = false;
611    bool            miss_wti_cmd_fifo_get     = p_vci_ini_int.cmdack.read();
612    vci_addr_t      miss_wti_cmd_fifo_address = 0;
613    vci_cmd_t       miss_wti_cmd_fifo_cmd     = 0;
614    vci_srcid_t     miss_wti_cmd_fifo_srcid   = 0;
615    vci_trdid_t     miss_wti_cmd_fifo_trdid   = 0;
616    vci_pktid_t     miss_wti_cmd_fifo_pktid   = 0;
617    int_data_t      miss_wti_cmd_fifo_wdata   = 0;
[984]618    vci_plen_t      miss_wti_cmd_fifo_plen    = 0;
[712]619
[240]620#ifdef INSTRUMENTATION
[715]621    m_cpt_fsm_dma_cmd           [r_dma_cmd_fsm.read()] ++;
622    m_cpt_fsm_dma_rsp           [r_dma_rsp_fsm.read() ] ++;
623    m_cpt_fsm_tlb               [r_tlb_fsm.read() ] ++;
624    m_cpt_fsm_config_cmd        [r_config_cmd_fsm.read() ] ++;
625    m_cpt_fsm_config_rsp        [r_config_rsp_fsm.read() ] ++;
[434]626    m_cpt_fsm_miss_wti_rsp      [r_miss_wti_rsp_fsm.read() ] ++;
[240]627#endif
628
629    m_cpt_total_cycles++;
630
[434]631    m_debug_activated  = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;
[240]632
[434]633    //////////////////////////////////////////////////////////////////////////////
[712]634    // The DMA_CMD_FSM handles transactions requested by peripherals.
635    // - it can be DMA transactions to RAM network (DMA_REQ state).
636    // - it can be WTI transactions to INT network (EXT_WTI_REQ state).
637    // It makes the address translation if IOMMU is activated, requesting
638    // the TLB_MISS FSM in case of TLB miss (TLB_MISS_WAIT state).
639    // When the IOMMU is activated, a DMA request can fail in two cases:
640    // - write to a read-only address : detected in IDLE state
641    // - virtual address unmapped     : detected in MISS_WAIT state
642    // In both cases of violation, the DMA_CMD FSM makes the following actions :
643    // 1. register the error in r_iommu_*** registers
644    // 2. wait the faulty command EOP (ERR_WAIT_EOP state)
645    // 3. request a IOMMU WTI to MISS_WTI FSM, (ERR_WTI_REQ state)
646    // 4. request a response error to DMA_RSP FSM (ERR_RSP_REQ state)
[240]647    ///////////////////////////////////////////////////////////////////////////////
648
[715]649    switch( r_dma_cmd_fsm.read() )
[240]650    {
[434]651    //////////////////
[712]652    case DMA_CMD_IDLE:  // wait a DMA or WTI VCI transaction and route it
653                        // after an IOMMU translation if IOMMU activated.
654                        // no VCI flit is consumed in this state
[240]655    {
[715]656        if ( p_vci_tgt_iox.cmdval.read() )
657        {
[984]658
659#if DEBUG_DMA_CMD
660if( m_debug_activated )
661std::cout << name()
662          << "  <IOB DMA_CMD_IDLE> DMA command"
663          << " : address = " << std::hex << p_vci_tgt_iox.address.read()
664          << " / srcid = " << p_vci_tgt_iox.srcid.read()
665          << " / wdata = " << std::hex << p_vci_tgt_iox.wdata.read()
666          << " / plen = " << std::dec << p_vci_tgt_iox.plen.read()
667          << " / eop = " << p_vci_tgt_iox.eop.read() << std::endl;
668#endif
669
[715]670            if ( not r_iommu_active.read() )    // tlb not activated
[240]671            {
[712]672                // save paddr address
673                r_dma_cmd_paddr = p_vci_tgt_iox.address.read();
674
675                // analyse paddr for WTI/DMA routing
676                // WTI requests must be single flit (READ or WRITE)
677                if ( is_wti( p_vci_tgt_iox.address.read() ) )
678                {
[715]679                    assert( p_vci_tgt_iox.eop.read() and
[712]680                    "ERROR in VCI_IOB illegal VCI WTI command from IOX network");
681
682                    r_dma_cmd_fsm = DMA_CMD_WTI_IOX_REQ;
683                }
684                else
685                {
686                    r_dma_cmd_fsm = DMA_CMD_DMA_REQ;
687                }
688
[240]689            }
[434]690            else if (r_tlb_fsm.read() == TLB_IDLE ||
[715]691                     r_tlb_fsm.read() == TLB_WAIT )   // tlb access possible
[240]692            {
[715]693                vci_addr_t  iotlb_paddr;
694                pte_info_t  iotlb_flags;
695                size_t      iotlb_way;
[240]696                size_t      iotlb_set;
[434]697                vci_addr_t  iotlb_nline;
[715]698                bool        iotlb_hit;
[240]699
700#ifdef INSTRUMENTATION
701m_cpt_iotlb_read++;
702#endif
[434]703                iotlb_hit = r_iotlb.translate(p_vci_tgt_iox.address.read(),
704                                              &iotlb_paddr,
705                                              &iotlb_flags,
706                                              &iotlb_nline,  // unused
[715]707                                              &iotlb_way,    // unused
[434]708                                              &iotlb_set );  // unused
[715]709
710                if ( iotlb_hit )                                 // tlb hit
711                {
712                    if ( not iotlb_flags.w and    // access right violation
713                        (p_vci_tgt_iox.cmd.read() == vci_param_ext::CMD_WRITE) )
[240]714                    {
[712]715                        // register error
[715]716                        r_iommu_etr      = MMU_WRITE_ACCES_VIOLATION;
[434]717                        r_iommu_bvar     = p_vci_tgt_iox.address.read();
718                        r_iommu_bad_id   = p_vci_tgt_iox.srcid.read();
[715]719
[712]720                        // prepare response error request to DMA_RSP FSM
721                        r_dma_cmd_to_dma_rsp_rsrcid = p_vci_tgt_iox.srcid.read();
722                        r_dma_cmd_to_dma_rsp_rtrdid = p_vci_tgt_iox.trdid.read();
723                        r_dma_cmd_to_dma_rsp_rpktid = p_vci_tgt_iox.pktid.read();
724
725                        // jumps IOMMU error sequence
726                        r_dma_cmd_fsm = DMA_CMD_ERR_WAIT_EOP;
[240]727#if DEBUG_DMA_CMD
[434]728if( m_debug_activated )
[715]729std::cout << name()
730          << "  <IOB DMA_CMD_IDLE> TLB HIT but writable violation" << std::endl;
[240]731#endif
732                    }
[434]733                    else                         // no access rights violation
734                    {
735#if DEBUG_DMA_CMD
736if( m_debug_activated )
[715]737std::cout << name()
738          << "  <IOB DMA_CMD_IDLE> TLB HIT" << std::endl;
[434]739#endif
[712]740                        // save paddr address
741                        r_dma_cmd_paddr = iotlb_paddr;
742
743                        // analyse address for WTI/DMA routing
744                        if ( is_wti( iotlb_paddr ) )
745                        {
[984]746                            assert( p_vci_tgt_iox.eop.read() &&
[712]747                            "ERROR in VCI_IOB illegal VCI WTI command from IOX network");
748
[715]749                            r_dma_cmd_fsm = DMA_CMD_WTI_IOX_REQ;
[712]750                        }
751                        else
752                        {
753                            r_dma_cmd_fsm = DMA_CMD_DMA_REQ;
754                        }
[434]755                    }
[240]756                }
[434]757                else                                             // TLB miss
[240]758                {
759
760#ifdef INSTRUMENTATION
761m_cpt_iotlb_miss++;
762#endif
[715]763                    // register virtual address, and send request to TLB FSM
764                    r_dma_cmd_to_tlb_vaddr = p_vci_tgt_iox.address.read();
[712]765                    r_dma_cmd_to_tlb_req   = true;
766                    r_dma_cmd_fsm          = DMA_CMD_TLB_MISS_WAIT;
[240]767#if DEBUG_DMA_CMD
[434]768if( m_debug_activated )
[715]769std::cout << name()
770          << "  <IOB DMA_CMD_IDLE> TLB MISS" << std::endl;
[240]771#endif
[715]772                } // end tlb miss
[240]773            } // end if tlb_activated
774        } // end if cmdval
775        break;
776    }
[712]777    /////////////////////
778    case DMA_CMD_DMA_REQ:    // put a flit in DMA_CMD FIFO
[715]779                             // if contig, VCI address must be incremented
[712]780                             // after initial translation by IOMMU.
781                             // flit is consumed if DMA_CMD FIFO not full
[240]782    {
[715]783        if ( p_vci_tgt_iox.cmdval && m_dma_cmd_addr_fifo.wok() )
[240]784        {
[715]785            // SRCID in RAM network is the concatenation of the IO bridge
786            // cluster id with the DMA peripheral local id
787            assert((m_srcid_gid_mask[p_vci_tgt_iox.srcid.read()] == 0) &&
788                    "error: external DMA peripherals global id must be 0");
[240]789
[715]790            dma_cmd_fifo_srcid = (m_srcid_gid_mask.mask() & m_int_srcid) |
791                                 p_vci_tgt_iox.srcid.read();
792            dma_cmd_fifo_put   = true;
793
794            if ( p_vci_tgt_iox.contig.read() )
795            {
796                r_dma_cmd_paddr = r_dma_cmd_paddr.read() + vci_param_ext::B;
797            }
798
799            if ( p_vci_tgt_iox.eop.read() )
800            {
801                r_dma_cmd_fsm = DMA_CMD_IDLE;
802            }
803
[240]804#if DEBUG_DMA_CMD
[715]805if( m_debug_activated )
806std::cout << name()
807          << "  <IOB DMA_CMD_FIFO_PUT_CMD> Push into DMA_CMD fifo:"
[434]808          << " address = " << std::hex << r_dma_cmd_paddr.read()
[715]809          << " srcid = " << dma_cmd_fifo_srcid
[434]810          << " wdata = " << p_vci_tgt_iox.wdata.read()
[712]811          << " plen = " << std::dec << p_vci_tgt_iox.plen.read()
812          << " eop = " << std::dec << p_vci_tgt_iox.eop.read() << std::endl;
[240]813#endif
814        }
815        break;
816    }
[712]817    /////////////////////////
[715]818    case DMA_CMD_WTI_IOX_REQ:    // post a WTI_IOX request to MISS_WTI FSM
[712]819                                 // if no prending previous request
[715]820                                 // command arguments are stored in dedicated registers
[712]821                                 // VCI flit is consumed if no previous request
[240]822    {
[712]823        if ( not r_dma_cmd_to_miss_wti_cmd_req.read() )  // no previous pending request
824        {
[715]825            // SRCID in INT network for WTI transactions is the concatenation
826            // of the IO bridge cluster id with the DMA peripheral local id
827            assert((m_srcid_gid_mask[p_vci_tgt_iox.srcid.read()] == 0) &&
828                    "error: external DMA peripherals global id must be 0");
829
830            vci_srcid_t wti_srcid = (m_srcid_gid_mask.mask() & m_int_srcid) | 
831                                    p_vci_tgt_iox.srcid.read();
832
[712]833            r_dma_cmd_to_miss_wti_cmd_req   = true;
834            r_dma_cmd_to_miss_wti_cmd_addr  = p_vci_tgt_iox.address.read();
835            r_dma_cmd_to_miss_wti_cmd_cmd   = p_vci_tgt_iox.cmd.read();
836            r_dma_cmd_to_miss_wti_cmd_wdata = (uint32_t)p_vci_tgt_iox.wdata.read();
[715]837            r_dma_cmd_to_miss_wti_cmd_srcid = wti_srcid;
[712]838            r_dma_cmd_to_miss_wti_cmd_trdid = p_vci_tgt_iox.trdid.read();
839            r_dma_cmd_to_miss_wti_cmd_pktid = PKTID_WTI_IOX;
840
841            r_dma_cmd_fsm = DMA_CMD_IDLE;
[715]842
[712]843#if DEBUG_DMA_CMD
[715]844if( m_debug_activated )
845std::cout << name()
846          << "  <IOB DMA_CMD_WTI_IOX_REQ> request WTI transaction from ext peripheral"
[712]847          << " : address = " << std::hex << r_dma_cmd_paddr.read()
[715]848          << " / srcid = " << wti_srcid
[712]849          << " / wdata = " << p_vci_tgt_iox.wdata.read() << std::endl;
850#endif
851        }
[240]852        break;
853    }
[434]854    //////////////////////////
[715]855    case DMA_CMD_ERR_WAIT_EOP:   // wait EOP before requesting WTI & error response
[712]856                                 // VCI flit is always consumed
[240]857    {
[712]858        if ( p_vci_tgt_iox.eop.read() ) r_dma_cmd_fsm = DMA_CMD_ERR_WTI_REQ;
859
860#if DEBUG_DMA_CMD
[715]861if( m_debug_activated )
862std::cout << name()
863          << "  <IOB DMA_CMD_WAIT_EOP> wait EOP for faulty DMA command" << std::endl;
[712]864#endif
865        break;
866    }
[715]867
[712]868    /////////////////////////
[715]869    case DMA_CMD_ERR_WTI_REQ:    // post a WTI_MMU request to MISS_WTI_CMD FSM
[712]870                                 // if no prending previous request
871                                 // response arguments are stored in dedicated registers
[715]872                                 // no VCI flit is consumed
[712]873    {
874        if ( not r_dma_cmd_to_miss_wti_cmd_req.read() )  // no pending previous request
[240]875        {
[712]876            r_dma_cmd_to_miss_wti_cmd_req   = true;
877            r_dma_cmd_to_miss_wti_cmd_addr  = (vci_addr_t)r_iommu_wti_addr_lo.read() |
878                                              (((vci_addr_t)r_iommu_wti_addr_hi.read())<<32);
879            r_dma_cmd_to_miss_wti_cmd_wdata = 0;
880            r_dma_cmd_to_miss_wti_cmd_srcid = m_int_srcid;
881            r_dma_cmd_to_miss_wti_cmd_trdid = 0;
882            r_dma_cmd_to_miss_wti_cmd_pktid = PKTID_WTI_MMU;
[434]883
[712]884            r_dma_cmd_fsm            = DMA_CMD_ERR_RSP_REQ;
[240]885
886#if DEBUG_DMA_CMD
[715]887if( m_debug_activated )
888std::cout << name()
889          << "  <IOB DMA_CMD_ERR_WTI_REQ> request an IOMMU WTI" << std::endl;
[240]890#endif
891        }
892        break;
893    }
[712]894    /////////////////////////
895    case DMA_CMD_ERR_RSP_REQ:    // post an error response request to DMA_RSP FSM
896                                 // if no prending previous request
897                                 // response arguments are stored in dedicated registers
[715]898                                 // no VCI flit is consumed
[240]899    {
[712]900        if ( not r_dma_cmd_to_dma_rsp_req.read() )  // no pending previous request
[240]901        {
[712]902            r_dma_cmd_to_dma_rsp_req    = true;
903            r_dma_cmd_to_dma_rsp_rerror = 0x1;
904            r_dma_cmd_to_dma_rsp_rdata  = 0;
905        }
906        break;
907    }
908    ///////////////////////////
909    case DMA_CMD_TLB_MISS_WAIT:  // waiting completion of a TLB miss
[715]910                                 // we must test a possible page fault error...
[712]911    {
912        if ( not r_dma_cmd_to_tlb_req.read() ) // TLB miss completed
913        {
[434]914            if ( r_tlb_miss_error.read() )   // Error reported by TLB FSM
[240]915            {
[715]916                r_iommu_etr     = MMU_READ_PT2_UNMAPPED;
[712]917                r_iommu_bvar    = r_dma_cmd_to_tlb_vaddr.read();
[434]918                r_iommu_bad_id  = p_vci_tgt_iox.srcid.read();
[712]919                r_dma_cmd_fsm   = DMA_CMD_ERR_WAIT_EOP;
[240]920            }
[434]921            else                            // No error
922            {
923                r_dma_cmd_fsm   = DMA_CMD_IDLE;
924            }
[240]925        }
926        break;
927    }
[434]928    } // end switch DMA_CMD FSM
[240]929
[712]930    ////////////////////////////////////////////////////////////////////////////////
931    // The DMA_RSP_FSM controls access to the DMA_RSP FIFO to the IOX network.
932    // There exist 3 "clients" to send VCI responses on the IOX network:
933    // - request from p_vci_ini_ram    : normal DMA response from RAM network,
934    // - request from MISS_WTI_RSP FSM : normal WTI response from INT network,
935    // - request from DMA_CMD FSM      : bad address error response
936    // This FSM implements a round robin priority, with a "dead cycle" between
937    // two transactions. It could be optimized if throughput is critical...
938    ////////////////////////////////////////////////////////////////////////////////
[434]939
[712]940    // does nothing if FIFO is full
941    if ( m_dma_rsp_rerror_fifo.wok() )
[240]942    {
[715]943        switch( r_dma_rsp_fsm.read() )
[712]944        {
945            //////////////////////
946            case DMA_RSP_IDLE_DMA:  // normal DMA response has highest priority
[715]947            {
[712]948                if     (p_vci_ini_ram.rspval.read())          r_dma_rsp_fsm = DMA_RSP_PUT_DMA;
949                else if(r_miss_wti_rsp_to_dma_rsp_req.read()) r_dma_rsp_fsm = DMA_RSP_PUT_WTI;
950                else if(r_dma_cmd_to_dma_rsp_req.read())      r_dma_rsp_fsm = DMA_RSP_PUT_ERR;
951                break;
952            }
953            //////////////////////
954            case DMA_RSP_IDLE_WTI:  // normal WTI response has highest priority
[715]955            {
956                if     (r_miss_wti_rsp_to_dma_rsp_req.read()) r_dma_rsp_fsm = DMA_RSP_PUT_WTI;
[712]957                else if(r_dma_cmd_to_dma_rsp_req.read())      r_dma_rsp_fsm = DMA_RSP_PUT_ERR;
958                else if(p_vci_ini_ram.rspval.read())          r_dma_rsp_fsm = DMA_RSP_PUT_DMA;
959                break;
960            }
961            //////////////////////
962            case DMA_RSP_IDLE_ERR:  // error  response has highest priority
[715]963            {
[712]964                if     (r_dma_cmd_to_dma_rsp_req.read())      r_dma_rsp_fsm = DMA_RSP_PUT_ERR;
965                else if(p_vci_ini_ram.rspval.read())          r_dma_rsp_fsm = DMA_RSP_PUT_DMA;
[715]966                else if(r_miss_wti_rsp_to_dma_rsp_req.read()) r_dma_rsp_fsm = DMA_RSP_PUT_WTI;
[712]967                break;
968            }
969            ///////////////////////
970            case DMA_RSP_PUT_DMA:  // put one flit of the DMA response into FIFO
[715]971            {
[712]972                dma_rsp_fifo_put    = true;
973                dma_rsp_fifo_rerror = p_vci_ini_ram.rerror.read();
974                dma_rsp_fifo_rdata  = p_vci_ini_ram.rdata.read();
[715]975                dma_rsp_fifo_rsrcid = m_srcid_lid_mask[p_vci_ini_ram.rsrcid.read()];
[712]976                dma_rsp_fifo_rtrdid = p_vci_ini_ram.rtrdid.read();
977                dma_rsp_fifo_rpktid = p_vci_ini_ram.rpktid.read();
978                dma_rsp_fifo_reop   = p_vci_ini_ram.reop.read();
[240]979
[712]980                // update priority
981                if ( p_vci_ini_ram.reop.read() ) r_dma_rsp_fsm = DMA_RSP_IDLE_WTI;
[240]982
983#if DEBUG_DMA_RSP
[715]984if( m_debug_activated )
985std::cout << name()
986          << "  <IOB DMA_RSP_PUT_DMA> Push DMA response into DMA_RSP FIFO"
987          << std::hex
988          << " : rsrcid = " << m_srcid_lid_mask[p_vci_ini_ram.rsrcid.read()]
[434]989          << " / rtrdid = " << p_vci_ini_ram.rtrdid.read()
[712]990          << " / rpktid = " << p_vci_ini_ram.rpktid.read()
991          << " / rdata = "  << p_vci_ini_ram.rdata.read()
[434]992          << " / rerror = " << p_vci_ini_ram.rerror.read()
[712]993          << " / reop = "   << p_vci_ini_ram.reop.read() << std::endl;
[240]994#endif
[712]995                break;
[715]996            }
[712]997            ///////////////////////
998            case DMA_RSP_PUT_WTI:  // put single flit WTI response into FIFO
[715]999            {
[712]1000                dma_rsp_fifo_put    = true;
1001                dma_rsp_fifo_rerror = r_miss_wti_rsp_to_dma_rsp_rerror.read();
1002                dma_rsp_fifo_rdata  = 0;
[715]1003                dma_rsp_fifo_rsrcid = 
1004                    m_srcid_lid_mask[r_miss_wti_rsp_to_dma_rsp_rsrcid.read()];
[712]1005                dma_rsp_fifo_rtrdid = r_miss_wti_rsp_to_dma_rsp_rtrdid.read();
1006                dma_rsp_fifo_rpktid = r_miss_wti_rsp_to_dma_rsp_rpktid.read();
1007                dma_rsp_fifo_reop   = true;
[240]1008
[712]1009                // acknowledge request
1010                r_miss_wti_rsp_to_dma_rsp_req = false;
[715]1011
[712]1012                // update priority
1013                r_dma_rsp_fsm = DMA_RSP_IDLE_ERR;
1014
1015#if DEBUG_DMA_RSP
[715]1016if( m_debug_activated )
1017std::cout << name()
1018          << "  <IOB DMA_RSP_PUT_WTI> Push WTI response into DMA_RSP FIFO"
1019          << std::hex
1020          << " : rsrcid = " << m_srcid_lid_mask[r_miss_wti_rsp_to_dma_rsp_rsrcid.read()]
[712]1021          << " / rtrdid = " << r_miss_wti_rsp_to_dma_rsp_rtrdid.read()
1022          << " / rpktid = " << r_miss_wti_rsp_to_dma_rsp_rpktid.read()
1023          << " / rdata = "  << 0
1024          << " / rerror = " << r_miss_wti_rsp_to_dma_rsp_rerror.read()
1025          << " / reop = "   << true << std::endl;
1026#endif
1027                break;
1028            }
1029            ///////////////////////
1030            case DMA_RSP_PUT_ERR:  // put sinfle flit error response into FIFO
1031            {
1032                dma_rsp_fifo_put    = true;
1033                dma_rsp_fifo_rerror = 0x1;
1034                dma_rsp_fifo_rdata  = 0;
1035                dma_rsp_fifo_rsrcid = r_dma_cmd_to_dma_rsp_rsrcid.read();
1036                dma_rsp_fifo_rtrdid = r_dma_cmd_to_dma_rsp_rtrdid.read();
1037                dma_rsp_fifo_rpktid = r_dma_cmd_to_dma_rsp_rpktid.read();
1038                dma_rsp_fifo_reop   = true;
1039
1040                // acknowledge request
1041                r_dma_cmd_to_dma_rsp_req = false;
[715]1042
[712]1043                // update priority
1044                r_dma_rsp_fsm = DMA_RSP_PUT_DMA;
1045
1046#if DEBUG_DMA_RSP
[715]1047if( m_debug_activated )
1048std::cout << name()
1049          << "  <IOB DMA_RSP_PUT_DMA> Push IOMMU ERROR response into DMA_RSP FIFO"
[712]1050          << " : rsrcid = " << std::hex << r_dma_cmd_to_dma_rsp_rsrcid.read()
1051          << " / rtrdid = " << r_dma_cmd_to_dma_rsp_rtrdid.read()
1052          << " / rpktid = " << r_dma_cmd_to_dma_rsp_rpktid.read()
1053          << " / rdata = "  << 0
1054          << " / rerror = " << r_dma_cmd_to_dma_rsp_rerror.read()
1055          << " / reop = "   << true << std::endl;
1056#endif
1057                break;
1058            }
[715]1059        } // end switch DMA_RSP FSM
[712]1060    }  // end if FIFO full
1061
1062
[434]1063    //////////////////////////////////////////////////////////////////////////////////
[712]1064    // The TLB FSM handles the TLB miss requests from DMA_CMD FSM,
[434]1065    // and the PTE inval request (from CONFIG_CMD FSM).
[715]1066    // PTE inval request have highest priority. In case of TLB miss,
[434]1067    // this fsm searchs the requested PTE on the prefetch buffer.
1068    // In case of buffer miss,  it request the MISS_WTI FSM to access the memory.
[240]1069    // It bypass the first level page table access if possible.
[712]1070    // It reset the r_dma_cmd_to_tlb_req flip-flop to signal TLB miss completion.
[434]1071    // An unexpected, but possible page fault is signaled in r_tlb_miss_error flip_flop.
[240]1072    ////////////////////////////////////////////////////////////////////////////////////
[434]1073
1074    switch (r_tlb_fsm.read())
[240]1075    {
[434]1076    //////////////
1077    case TLB_IDLE:   // In case of TLB miss request, chek the prefetch buffer first
1078                     // PTE inval request are handled as unmaskable interrupts
[240]1079    {
[715]1080        if ( r_config_cmd_to_tlb_req.read() ) // Request for a PTE invalidation
[240]1081        {
[712]1082            r_config_cmd_to_tlb_req  = false;
1083            r_waiting_transaction    = false;
1084            r_tlb_fsm                = TLB_INVAL_CHECK;
[240]1085        }
[434]1086
[715]1087        else if ( r_dma_cmd_to_tlb_req.read() )   // request for a TLB Miss
[240]1088        {
[434]1089            // Checking prefetch buffer
[984]1090            if( r_tlb_buf_valid.read() )
[240]1091            {
[984]1092                if ( !r_tlb_buf_big_page.read() &&  // Hit on prefetch buffer and small page => PTE2
[715]1093                    (r_tlb_buf_vaddr.read() ==
[984]1094                    (r_dma_cmd_to_tlb_vaddr.read() & ~PTE2_LINE_OFFSET & ~K_PAGE_OFFSET_MASK)))
[434]1095                {
[984]1096                    size_t   pte_offset = (r_dma_cmd_to_tlb_vaddr.read() & PTE2_LINE_OFFSET) >> 12;
[434]1097                    uint32_t pte_flags  = r_tlb_buf_data[2*pte_offset];
[715]1098                    uint32_t pte_ppn    = r_tlb_buf_data[2*pte_offset+1];
1099
[434]1100                    // Bit valid checking
[715]1101                    if ( not ( pte_flags & PTE_V_MASK) )    // unmapped
[434]1102                    {
[715]1103                        std::cout << "VCI_IO_BRIDGE ERROR : " << name()
[434]1104                                  << " Page Table entry unmapped" << std::endl;
[715]1105
[434]1106                        r_tlb_miss_error = true;
[712]1107                        r_dma_cmd_to_tlb_req    = false;
[434]1108#if DEBUG_TLB_MISS
1109if ( m_debug_activated )
[715]1110std::cout << name()
1111          << "  <IOB TLB_IDLE> PTE2 Unmapped" << std::hex
[434]1112          << " / paddr = " << r_tlb_paddr.read()
1113          << " / PTE_FLAGS = " << pte_flags
1114          << " / PTE_PPN = " << pte_ppn << std::endl;
[240]1115#endif
[715]1116                        break;
[434]1117                    }
[240]1118
[434]1119                    // valid PTE2 : we must update the TLB
[715]1120                    r_tlb_pte_flags = pte_flags;
[434]1121                    r_tlb_pte_ppn   = pte_ppn;
1122                    r_tlb_fsm       = TLB_PTE2_SELECT;
1123#if DEBUG_TLB_MISS
1124if ( m_debug_activated )
[715]1125std::cout << name()
1126          << "  <IOB TLB_IDLE> Hit on prefetch buffer: PTE2" << std::hex
1127          << " / PTE_FLAGS = " << pte_flags
[434]1128          << " / PTE_PPN = " << pte_ppn << std::endl;
[240]1129#endif
[715]1130                    break;
[434]1131                }
[984]1132
1133                if( r_tlb_buf_big_page.read() &&         // Hit on prefetch buffer and big page
[715]1134                    (r_tlb_buf_vaddr.read() ==
[984]1135                    (r_dma_cmd_to_tlb_vaddr.read() & ~PTE1_LINE_OFFSET & ~M_PAGE_OFFSET_MASK )))
[434]1136                {
[984]1137                    size_t   pte_offset = (r_dma_cmd_to_tlb_vaddr.read() & PTE1_LINE_OFFSET) >> 21;
[434]1138                    uint32_t pte_flags  = r_tlb_buf_data[pte_offset];
[715]1139
[434]1140                    // Bit valid checking
[715]1141                    if ( not ( pte_flags & PTE_V_MASK) )    // unmapped
[434]1142                    {
[715]1143                        std::cout << "VCI_IO_BRIDGE ERROR : " << name()
[434]1144                                  << " Page Table entry unmapped" << std::endl;
[715]1145
[434]1146                        r_tlb_miss_error = true;
[712]1147                        r_dma_cmd_to_tlb_req    = false;
[434]1148#if DEBUG_TLB_MISS
1149if ( m_debug_activated )
[715]1150std::cout << name()
1151          << "  <IOB TLB_IDLE> PTE1 Unmapped" << std::hex
[434]1152          << " / paddr = " << r_tlb_paddr.read()
1153          << " / PTE = " << pte_flags << std::endl;
[240]1154#endif
[715]1155                        break;
[434]1156                    }
[240]1157
[434]1158#if DEBUG_TLB_MISS
1159if ( m_debug_activated )
[715]1160std::cout << name()
1161          << "  <IOB TLB_PTE1_GET> Hit on prefetch buffer: PTE1" << std::hex
[434]1162          << " / paddr = " << r_tlb_paddr.read()
1163          << std::hex << " / PTE1 = " << pte_flags << std::endl;
[240]1164#endif
[984]1165                    // valid PTE1 : we must update the TLB
1166                    r_tlb_pte_flags = pte_flags;
1167                    r_tlb_fsm       = TLB_PTE1_SELECT;
1168
[434]1169                    break;
[240]1170                }
1171            }
[715]1172
[434]1173            // prefetch buffer miss
[715]1174            r_tlb_fsm = TLB_MISS;
[240]1175
[434]1176#if DEBUG_TLB_MISS
1177if ( m_debug_activated )
[715]1178std::cout << name()
1179          << "  <IOB TLB_IDLE> Miss on prefetch buffer"
[712]1180          << std::hex << " / vaddr = " << r_dma_cmd_to_tlb_vaddr.read() << std::endl;
[240]1181#endif
1182        }
[984]1183
[240]1184        break;
1185    }
[434]1186    //////////////
1187    case TLB_MISS: // handling tlb miss
[240]1188    {
[715]1189        uint32_t    ptba = 0;
1190        bool        bypass;
1191        vci_addr_t  pte_paddr;
[240]1192
[434]1193#ifdef INSTRUMENTATION
1194m_cpt_iotlbmiss_transaction++;
1195#endif
[240]1196        // evaluate bypass in order to skip first level page table access
[712]1197        bypass = r_iotlb.get_bypass(r_dma_cmd_to_tlb_vaddr.read(), &ptba);
[715]1198
1199        // Request MISS_WTI_FSM a transaction on INT Network
[240]1200        if ( not bypass )     // Read PTE1/PTD1 in XRAM
1201        {
[984]1202            pte_paddr =
1203                ((vci_addr_t)r_iommu_ptpr.read() << (INDEX1_NBITS+2)) |
1204                ((vci_addr_t)(r_dma_cmd_to_tlb_vaddr.read() >> PAGE_M_NBITS) << 2);
1205            r_tlb_paddr               = pte_paddr;
1206            r_tlb_to_miss_wti_cmd_req = true;
1207            r_tlb_miss_type           = PTE1_MISS;
1208            r_tlb_fsm                 = TLB_WAIT;
[434]1209
1210#if DEBUG_TLB_MISS
1211if ( m_debug_activated )
[715]1212std::cout << name()
[984]1213          << "  <IOB TLB_MISS> Read PTE1/PTD1 in memory: PADDR = " << std::hex
1214          << pte_paddr << std::dec << std::endl;
[434]1215#endif
[240]1216        }
1217        else                  // Read PTE2 in XRAM
1218        {
[434]1219
1220#if DEBUG_TLB_MISS
1221if ( m_debug_activated )
[715]1222std::cout << name()
1223          << "  <IOB TLB_MISS> Read PTE2 in memory" << std::endl;
[434]1224#endif
[240]1225            //&PTE2 = PTBA + IX2 * 8
[984]1226            pte_paddr =
1227                ((vci_addr_t)ptba << PAGE_K_NBITS) |
1228                ((vci_addr_t)(r_dma_cmd_to_tlb_vaddr.read()&PTD_ID2_MASK)>>(PAGE_K_NBITS-3));
1229            r_tlb_paddr               = pte_paddr;
[712]1230            r_tlb_to_miss_wti_cmd_req = true;
1231            r_tlb_miss_type           = PTE2_MISS;
1232            r_tlb_fsm                 = TLB_WAIT;
[240]1233        }
1234
1235        break;
1236    }
[715]1237    //////////////////
1238    case TLB_PTE1_GET:  // Try to read a PT1 entry in the miss buffer
[240]1239    {
[715]1240
[240]1241        uint32_t  entry;
[715]1242
[434]1243        vci_addr_t line_number  = (vci_addr_t)((r_tlb_paddr.read())&(CACHE_LINE_MASK));
1244        size_t word_position = (size_t)( ((r_tlb_paddr.read())&(~CACHE_LINE_MASK))>>2 );
[240]1245
[715]1246        // Hit test. Just to verify.
[240]1247        // Hit must happen, since we've just finished its' miss transaction
[984]1248        bool hit = (r_tlb_buf_valid && (r_tlb_buf_tag.read() == line_number) );
1249        assert(hit && "Error: No hit on prefetch buffer after Miss Transaction");
[715]1250
[434]1251        entry = r_tlb_buf_data[word_position];
[715]1252
[240]1253        // Bit valid checking
[715]1254        if ( not ( entry & PTE_V_MASK) )    // unmapped
[240]1255        {
1256            //must not occur!
[434]1257            std::cout << "IOMMU ERROR " << name() << "TLB_IDLE state" << std::endl
[240]1258                      << "The Page Table entry ins't valid (unmapped)" << std::endl;
[715]1259
[434]1260            r_tlb_miss_error       = true;
[712]1261            r_dma_cmd_to_tlb_req   = false;
[715]1262            r_tlb_fsm              = TLB_IDLE;
[434]1263
1264#if DEBUG_TLB_MISS
1265if ( m_debug_activated )
[240]1266{
[984]1267std::cout << name()
1268          << "  <IOB DMA_PTE1_GET> First level entry Unmapped"
1269          << std::hex << " / paddr = " << r_tlb_paddr.read()
1270          << std::hex << " / PTE = " << entry << std::endl;
[240]1271}
1272#endif
[984]1273            break;
[240]1274        }
[715]1275
1276        if( entry & PTE_T_MASK )    //  PTD : me must access PT2
[240]1277        {
1278            // register bypass
[712]1279            r_iotlb.set_bypass( r_dma_cmd_to_tlb_vaddr.read(),
[715]1280                                entry & ((1 << (vci_param_int::N-PAGE_K_NBITS)) - 1),
1281                                0); //nline, unused
[240]1282
[712]1283            // &PTE2 = PTBA + IX2 * 8
[240]1284            // ps: PAGE_K_NBITS corresponds also to the size of a second level page table
[984]1285            r_tlb_paddr =
1286                (((vci_addr_t)entry & ((1ULL<<(vci_param_int::N-PAGE_K_NBITS))-1)) << PAGE_K_NBITS) |
1287                (((vci_addr_t)(r_dma_cmd_to_tlb_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
[434]1288
[712]1289            r_tlb_to_miss_wti_cmd_req = true;
1290            r_tlb_miss_type           = PTE2_MISS;
1291            r_tlb_fsm                 = TLB_WAIT;
1292
[240]1293#ifdef INSTRUMENTATION
1294m_cpt_iotlbmiss_transaction++;
1295#endif
1296
[434]1297#if DEBUG_TLB_MISS
1298if ( m_debug_activated )
[715]1299std::cout << name()
1300          << "  <IOB TLB_PTE1_GET> Success. Search PTE2" << std::hex
[434]1301          << " / PADDR = " << r_tlb_paddr.read()
1302          << " / PTD = " << entry << std::endl;
[240]1303#endif
1304        }
[715]1305        else            //  PTE1 :  we must update the IOTLB
[240]1306                        //  Should not occur if working only with small pages
1307        {
[984]1308            r_tlb_pte_flags = entry;
1309            r_tlb_fsm       = TLB_PTE1_SELECT;
[240]1310
[434]1311#if DEBUG_TLB_MISS
1312if ( m_debug_activated )
[715]1313std::cout << name()
1314          << "  <IOB TLB_PTE1_GET> Success. Big page"
[434]1315          << std::hex << " / paddr = " << r_tlb_paddr.read()
1316          << std::hex << " / PTE1 = " << entry << std::endl;
[240]1317#endif
1318        }
1319        break;
1320    }
[434]1321    /////////////////////
[715]1322    case TLB_PTE1_SELECT:   // select a slot for PTE1
[240]1323    {
[715]1324        size_t  way;
1325        size_t  set;
1326
[984]1327        r_iotlb.select( r_dma_cmd_to_tlb_vaddr.read(),
[715]1328                        true,  // PTE1
[240]1329                        &way,
1330                        &set );
1331#ifdef INSTRUMENTATION
1332m_cpt_iotlb_read++;
1333#endif
1334
[434]1335#if DEBUG_TLB_MISS
1336if ( m_debug_activated )
[715]1337std::cout << name()
1338          << "  <IOB TLB_PTE1_SELECT> Select a slot in TLB"
[434]1339          << " / way = " << std::dec << way
1340          << " / set = " << set << std::endl;
[240]1341#endif
[434]1342        r_tlb_way = way;
1343        r_tlb_set = set;
[984]1344        r_tlb_fsm = TLB_PTE1_UPDT;
[240]1345        break;
1346    }
[434]1347    ///////////////////
1348    case TLB_PTE1_UPDT:     // write a new PTE1 in tlb
1349                            // not necessary to treat the L/R bit
[240]1350    {
[984]1351        uint32_t pte = r_tlb_pte_flags.read();
[715]1352
[240]1353        // update TLB
[715]1354        r_iotlb.write( true,        // 2M page
[984]1355                       pte,
1356                       0,        // argument unused for a PTE1
1357                       r_dma_cmd_to_tlb_vaddr.read(),
1358                       r_tlb_way.read(),
1359                       r_tlb_set.read(),
1360                       0 );      //we set nline = 0
[712]1361
[240]1362#ifdef INSTRUMENTATION
1363m_cpt_iotlb_write++;
1364#endif
1365
[434]1366#if DEBUG_TLB_MISS
1367if ( m_debug_activated )
[240]1368{
[715]1369std::cout << name()
1370          << "  <IOB TLB_PTE1_UPDT> write PTE1 in TLB"
[434]1371          << " / set = " << std::dec << r_tlb_set.read()
1372          << " / way = " << r_tlb_way.read() << std::endl;
1373r_iotlb.printTrace();
[240]1374}
1375#endif
1376        // next state
[715]1377        r_tlb_fsm = TLB_RETURN; // exit sub-fsm
[240]1378        break;
1379    }
[434]1380    //////////////////
[715]1381    case TLB_PTE2_GET:  // Try to read a PTE2 (64 bits) in the miss buffer
1382    {
1383        uint32_t    pte_flags;
1384        uint32_t    pte_ppn;
1385
[434]1386        vci_addr_t line_number  = (vci_addr_t)((r_tlb_paddr.read())&(CACHE_LINE_MASK));
1387        size_t word_position = (size_t)( ((r_tlb_paddr.read())&(~CACHE_LINE_MASK))>>2 );
[715]1388
[240]1389        // Hit test. Just to verify.
[984]1390        bool hit = (r_tlb_buf_valid && (r_tlb_buf_tag.read() == line_number) );
[715]1391        assert(hit and "Error: No hit on prefetch buffer after Miss Transaction");
[434]1392        pte_flags= r_tlb_buf_data[word_position];
1393        pte_ppn= r_tlb_buf_data[word_position+1]; //because PTE2 is 2 words long
[240]1394        // Bit valid checking
[715]1395        if ( not ( pte_flags & PTE_V_MASK) )    // unmapped
[240]1396        {
1397            //must not occur!
[434]1398            std::cout << "IOMMU ERROR " << name() << "TLB_IDLE state" << std::endl
[240]1399                      << "The Page Table entry ins't valid (unmapped)" << std::endl;
[715]1400
[984]1401            r_tlb_miss_error      = true;
1402            r_dma_cmd_to_tlb_req  = false;
[715]1403            r_tlb_fsm             = TLB_IDLE;
[434]1404
1405#if DEBUG_TLB_MISS
1406if ( m_debug_activated )
[715]1407std::cout << name()
1408          << "  <IOB TLB_PTE2_GET> PTE2 Unmapped" << std::hex
[434]1409          << " / PADDR = " << r_tlb_paddr.read()
1410          << " / PTE = " << pte_flags << std::endl;
[240]1411#endif
[715]1412            break;
[240]1413        }
[715]1414
1415        r_tlb_pte_flags       = pte_flags;
[434]1416        r_tlb_pte_ppn         = pte_ppn;
1417        r_tlb_fsm           = TLB_PTE2_SELECT;
[715]1418
[434]1419#if DEBUG_TLB_MISS
1420if ( m_debug_activated )
[715]1421std::cout << name()
1422          << "  <IOB TLB_PTE2_GET> Mapped" << std::hex
1423          << " / PTE_FLAGS = " << pte_flags
[434]1424          << " / PTE_PPN = " << pte_ppn << std::endl;
[240]1425#endif
1426        break;
1427    }
1428    ////////////////////////////
[434]1429    case TLB_PTE2_SELECT:    // select a slot for PTE2
[240]1430    {
1431        size_t way;
1432        size_t set;
1433
[712]1434        r_iotlb.select( r_dma_cmd_to_tlb_vaddr.read(),
[715]1435                        false,  // PTE2
[240]1436                        &way,
1437                        &set );
1438#ifdef INSTRUMENTATION
1439m_cpt_iotlb_read++;
1440#endif
1441
[434]1442#if DEBUG_TLB_MISS
1443if ( m_debug_activated )
[715]1444std::cout << name()
1445          << "  <IOB TLB_PTE2_SELECT> Select a slot in IOTLB:"
[712]1446          << " way = " << std::dec << way
1447          << " / set = " << set << std::endl;
[240]1448#endif
[434]1449        r_tlb_way = way;
1450        r_tlb_set = set;
1451        r_tlb_fsm     = TLB_PTE2_UPDT;
[240]1452        break;
1453    }
[434]1454    ///////////////////
[715]1455    case TLB_PTE2_UPDT:         // write a new PTE2 in tlb
[434]1456                                // not necessary to treat the L/R bit
[240]1457    {
[984]1458        uint32_t pte_flags = r_tlb_pte_flags.read();
1459        uint32_t pte_ppn   = r_tlb_pte_ppn.read();
[715]1460
[240]1461        // update TLB for a PTE2
[715]1462        r_iotlb.write( false,   // 4K page
[240]1463                       pte_flags,
1464                       pte_ppn,
[715]1465                       r_dma_cmd_to_tlb_vaddr.read(),
1466                       r_tlb_way.read(),
[434]1467                       r_tlb_set.read(),
[240]1468                       0 );     // nline = 0
1469#ifdef INSTRUMENTATION
1470m_cpt_iotlb_write++;
1471#endif
1472
[434]1473#if DEBUG_TLB_MISS
1474if ( m_debug_activated )
[240]1475{
[715]1476std::cout << name()
1477          << "  <IOB TLB_PTE2_UPDT> write PTE2 in IOTLB"
[712]1478          << " / set = " << std::dec << r_tlb_set.read()
1479          << " / way = " << r_tlb_way.read() << std::endl;
1480r_iotlb.printTrace();
[240]1481}
1482#endif
1483        // next state
[715]1484        r_tlb_fsm = TLB_RETURN;
[240]1485        break;
1486    }
[434]1487    //////////////
1488    case TLB_WAIT:   // waiting completion of a miss transaction from MISS_WTI FSM
1489                     // PTE inval request are handled as unmaskable interrupts
[240]1490    {
[715]1491        if ( r_config_cmd_to_tlb_req.read() ) // Request for a PTE invalidation
[240]1492        {
[712]1493            r_config_cmd_to_tlb_req = false;
1494            r_waiting_transaction   = true;
1495            r_tlb_fsm               = TLB_INVAL_CHECK;
[240]1496        }
1497
1498#ifdef INSTRUMENTATION
1499m_cost_iotlbmiss_transaction++;
1500#endif
[984]1501        if ( r_miss_wti_rsp_to_tlb_done.read() ) // Miss transaction completed
[715]1502        {
[984]1503            r_miss_wti_rsp_to_tlb_done = false;
1504
1505            r_tlb_buf_valid = true;
1506            r_tlb_buf_vaddr = r_dma_cmd_to_tlb_vaddr.read();
1507            r_tlb_buf_tag   = r_tlb_paddr.read() & CACHE_LINE_MASK;
1508
[715]1509            if ( r_miss_wti_rsp_error_miss.read() ) // bus error reported
1510            {
[712]1511                r_miss_wti_rsp_error_miss = false;
1512                r_tlb_miss_error          = true;
1513                r_dma_cmd_to_tlb_req      = false;
1514                r_tlb_fsm                 = TLB_IDLE;
[240]1515            }
1516            else if(r_tlb_miss_type == PTE1_MISS)
1517            {
[984]1518                r_tlb_buf_big_page = true;
[715]1519                r_tlb_fsm = TLB_PTE1_GET;
[240]1520            }
1521            else
1522            {
[984]1523                r_tlb_buf_big_page = false;
[434]1524                r_tlb_fsm = TLB_PTE2_GET;
[240]1525            }
1526        }
1527        break;
1528    }
[434]1529    ////////////////
[712]1530    case TLB_RETURN:   // reset r_dma_cmd_to_tlb_req to signal TLB miss completion
1531                       // possible errors are signaled through r_tlb_miss_error
[240]1532    {
[434]1533#if DEBUG_TLB_MISS
1534if ( m_debug_activated )
[715]1535std::cout << name()
1536          << "  <IOB TLB_RETURN> IOTLB MISS completed" << std::endl;
[240]1537#endif
[712]1538        r_dma_cmd_to_tlb_req  = false;
[434]1539        r_tlb_fsm = TLB_IDLE;
[240]1540        break;
1541    }
[434]1542    /////////////////////
1543    case TLB_INVAL_CHECK:   // request from CONFIG_FSM to invalidate all PTE in a given line
1544                            // checks the necessity to invalidate prefetch buffer
[240]1545    {
1546        // If a transaction is pending, no need to invalidate the prefetch
1547        // We can ignore it, since we'll replace the line.
1548        // The new line is necessarily up-to-date
[434]1549        if(!r_waiting_transaction.read() && r_tlb_buf_valid)
[240]1550        {
[434]1551            if(!r_tlb_buf_big_page)
[240]1552            {
[715]1553               if( r_tlb_buf_vaddr.read() ==
1554                   (r_config_cmd_to_tlb_vaddr.read()& ~PTE2_LINE_OFFSET) )
[240]1555                // The virtual address corresponds to one entry on the buffer line
1556                {
[434]1557                    r_tlb_buf_valid = false;   //change here for individual invalidation
[240]1558                }
1559            }
1560            else    // First level entries on buffer. Unused if only small pages
1561            {
[715]1562               if( r_tlb_buf_vaddr.read() ==
1563                   (r_config_cmd_to_tlb_vaddr.read()& ~PTE1_LINE_OFFSET) )
[240]1564                // The virtual address corresponds to one entry on the buffer line
1565                {
[434]1566                    r_tlb_buf_valid = false;   //change here for individual invalidation
[240]1567                }
1568            }
1569        }
[715]1570
[240]1571        // Invalidation on IOTLB
[715]1572        r_iotlb.inval(r_config_cmd_to_tlb_vaddr.read());
1573
1574        if(r_waiting_transaction.read()) r_tlb_fsm =TLB_WAIT;
[434]1575        else r_tlb_fsm = TLB_IDLE;
[715]1576        break;
[240]1577    }
[434]1578    } //end switch r_tlb_fsm
[715]1579
[434]1580    ////////////////////////////////////////////////////////////////////////////////
1581    // The CONFIG_CMD_FSM handles the VCI commands from the INT network.
[712]1582    // - it can be single flit config transactions
1583    // - it can be multi-flits data transactions to ROM (read) or FBF (write).
[585]1584    // The write burst transactions must be serialised from 32 to 64 bits width.
[451]1585    // The configuration requests can be local (IO_BRIDGE config registers)
1586    // or remote (config registers of peripherals on IOX network).
[712]1587    // - The local configuration segment is identified by the "special" atribute
1588    //   in the mapping table.
[713]1589    // - All configuration requests are checked against segmentation violation.
[451]1590    // - In case of local config request, or in case of segmentation violation,
[712]1591    //   the FSM send a response request to CONFIG_RSP FSM.
[585]1592    // - In case of remote transaction, it put the VCI command in CONFIG_CMD fifo,
1593    //   and this require two cycles per IOX flit in case of write burst.
[434]1594    ///////////////////////////////////////////////////////////////////////////////
[240]1595
[715]1596    switch( r_config_cmd_fsm.read() )
[240]1597    {
[434]1598    /////////////////////
[585]1599    case CONFIG_CMD_IDLE:   // A VCI INT command is always consumed in this state
[240]1600    {
[715]1601        if ( p_vci_tgt_int.cmdval.read() )
[240]1602        {
[434]1603
[240]1604#if DEBUG_CONFIG_CMD
[434]1605if( m_debug_activated )
[715]1606std::cout << name()
[763]1607          << "  <IOB CONFIG_CMD_IDLE> Config Command received" << std::endl
[585]1608          << "  address = " << std::hex << p_vci_tgt_int.address.read()
1609          << " / srcid = " << p_vci_tgt_int.srcid.read()
[434]1610          << " / trdid = " << p_vci_tgt_int.trdid.read()
[715]1611          << " / pktid = " << p_vci_tgt_int.pktid.read()
[434]1612          << " / wdata = " << std::hex << p_vci_tgt_int.wdata.read()
1613          << " / be = " << p_vci_tgt_int.be.read()
1614          << " / plen = " << std::dec << p_vci_tgt_int.plen.read()
1615          << " / eop = " << p_vci_tgt_int.eop.read() << std::endl;
[240]1616#endif
[434]1617            vci_addr_t paddr = p_vci_tgt_int.address.read();
1618            bool       read  = (p_vci_tgt_int.cmd.read() == vci_param_int::CMD_READ);
[715]1619            uint32_t   cell  = (uint32_t)((paddr & 0x1FF)>>2);
[585]1620            bool       eop   = p_vci_tgt_int.eop.read();
1621            bool       high  = (paddr & 0x4);
[715]1622            ext_data_t wdata = (ext_data_t)p_vci_tgt_int.wdata.read();
1623            ext_be_t   be    = (ext_be_t)p_vci_tgt_int.be.read();
[585]1624
[451]1625            // chek segments
1626            std::list<soclib::common::Segment>::iterator seg;
[549]1627            bool found   = false;
1628            bool special = false;
[715]1629            for ( seg = m_int_seglist.begin() ;
[451]1630                  seg != m_int_seglist.end() and not found ; seg++ )
1631            {
[715]1632                if ( seg->contains(paddr) )
[549]1633                {
1634                   found   = true;
1635                   special = seg->special();
1636                }
[451]1637            }
[715]1638
[549]1639            if ( found and special )  // IO_BRIDGE itself
[240]1640            {
[585]1641                bool rerror = false;
[715]1642                int_data_t rdata;
[434]1643
[715]1644                assert( (be == 0xF) and
[712]1645                "ERROR in vci_io_bridge : BE must be 0xF for a config access");
[585]1646
1647                assert( ( eop ) and
1648                "ERROR in vci_io_bridge : local config access must be one flit");
1649
[984]1650#if DEBUG_CONFIG_CMD
1651if( m_debug_activated )
1652std::cout << name()
1653          << "  <IOB CONFIG_CMD_IDLE> Command on IOB configuration registers" << std::endl;
1654#endif
1655
[434]1656                if ( not read && (cell == IOB_IOMMU_PTPR) )       // WRITE PTPR
[240]1657                {
[715]1658                    r_iommu_ptpr = (uint32_t)wdata;
[984]1659
1660#if DEBUG_CONFIG_CMD
1661if( m_debug_activated )
1662std::cout << name()
1663          << "  <IOB CONFIG_CMD_IDLE> Write IOB_IOMMU_PTPR: / wdata = " << std::hex
1664          << wdata << std::dec << std::endl;
1665#endif
[434]1666                }
[715]1667                else if ( read && (cell == IOB_IOMMU_PTPR) )      // READ PTPR
[240]1668                {
[715]1669                    rdata = r_iommu_ptpr.read();
[984]1670
1671#if DEBUG_CONFIG_CMD
1672if( m_debug_activated )
1673std::cout << name()
1674          << "  <IOB CONFIG_CMD_IDLE> Read IOB_IOMMU_PTPR: / rdata = " << std::hex
1675          << rdata << std::dec << std::endl;
1676#endif
[240]1677                }
[984]1678                else if ( not read && (cell == IOB_IOMMU_ACTIVE) )     // WRITE ACTIVE
[240]1679                {
[984]1680                    r_iommu_active = wdata ? true : false;
1681
1682#if DEBUG_CONFIG_CMD
1683if( m_debug_activated )
1684std::cout << name()
1685          << "  <IOB CONFIG_CMD_IDLE> Write IOB_IOMMU_ACTIVE: / wdata = " << std::hex
1686          << wdata << std::dec << std::endl;
1687#endif
1688                }
1689                else if ( read && (cell == IOB_IOMMU_ACTIVE) )    // READ ACTIVE
1690                {
1691                    rdata = r_iommu_active.read();
1692
1693#if DEBUG_CONFIG_CMD
1694if( m_debug_activated )
1695std::cout << name()
1696          << "  <IOB CONFIG_CMD_IDLE> Read IOB_IOMMU_ACTIVE: / rdata = " << std::hex
1697          << rdata << std::dec << std::endl;
1698#endif
1699                }
1700                else if( not read && (cell == IOB_WTI_ENABLE))    // WRITE WTI_ENABLE
1701                {
[715]1702                    r_iommu_wti_enable = wdata;
[240]1703                }
[984]1704                else if( read && (cell == IOB_WTI_ENABLE))        // READ WTI ENABLE
[240]1705                {
[715]1706                    rdata = r_iommu_wti_enable.read();
[240]1707                }
[434]1708                else if( read && (cell == IOB_IOMMU_BVAR))        // READ BVAR
[240]1709                {
[715]1710                    rdata = r_iommu_bvar.read();
[240]1711                }
[984]1712                else if( read && (cell == IOB_IOMMU_ETR))         // READ ETR
[240]1713                {
[715]1714                    rdata = r_iommu_etr.read();
[240]1715                }
[434]1716                else if( read && (cell == IOB_IOMMU_BAD_ID))      // READ BAD_ID
[240]1717                {
[715]1718                    rdata = r_iommu_bad_id.read();
[240]1719                }
[434]1720                else if( not read && (cell == IOB_INVAL_PTE))     // WRITE INVAL_PTE
[240]1721                {
[712]1722                    r_config_cmd_to_tlb_req   = true;
[715]1723                    r_config_cmd_to_tlb_vaddr = (uint32_t)wdata;
[240]1724                }
[984]1725                else if( not read && (cell == IOB_WTI_ADDR_LO))   // WRITE WTI_PADDR_LO
[240]1726                {
[715]1727                    r_iommu_wti_addr_lo = (vci_addr_t)wdata;
[240]1728                }
[984]1729                else if( read && (cell == IOB_WTI_ADDR_LO))       // READ WTI_PADDR_LO
[240]1730                {
[715]1731                    rdata = r_iommu_wti_addr_lo.read();
[240]1732                }
[984]1733                else if( not read && (cell == IOB_WTI_ADDR_HI))   // WRITE WTI_PADDR_HI
[240]1734                {
[715]1735                    r_iommu_wti_addr_hi = (vci_addr_t)wdata;
[240]1736                }
[984]1737                else if( read && (cell == IOB_WTI_ADDR_HI))       // READ WTI_PADDR_HI
[240]1738                {
[715]1739                    rdata = r_iommu_wti_addr_hi.read();
[240]1740                }
[434]1741                else   // Error: Wrong address, or invalid operation.
1742                {
1743                    rerror = true;
1744                }
[712]1745                r_config_cmd_to_config_rsp_rerror = rerror;
[715]1746                r_config_cmd_to_config_rsp_rdata  = rdata;
1747                r_config_cmd_to_config_rsp_rsrcid = p_vci_tgt_int.srcid.read();
1748                r_config_cmd_to_config_rsp_rtrdid = p_vci_tgt_int.trdid.read();
1749                r_config_cmd_to_config_rsp_rpktid = p_vci_tgt_int.pktid.read();
1750                r_config_cmd_fsm                  = CONFIG_CMD_RSP;
[240]1751            }
[451]1752            else if ( found )                            // remote peripheral
[240]1753            {
[715]1754                // buffer VCI command
[585]1755                r_config_cmd_address = p_vci_tgt_int.address.read();
1756                r_config_cmd_pktid   = p_vci_tgt_int.pktid.read();
1757                r_config_cmd_plen    = p_vci_tgt_int.plen.read();
1758                r_config_cmd_cmd     = p_vci_tgt_int.cmd.read();
1759                r_config_cmd_cons    = p_vci_tgt_int.cons.read();
1760                r_config_cmd_clen    = p_vci_tgt_int.clen.read();
1761                r_config_cmd_wrap    = p_vci_tgt_int.wrap.read();
1762                r_config_cmd_contig  = p_vci_tgt_int.contig.read();
1763                r_config_cmd_cfixed  = p_vci_tgt_int.cfixed.read();
[715]1764                r_config_cmd_eop     = eop;
1765                r_config_cmd_wdata   = (wdata << (high ? 32 : 0));
1766                r_config_cmd_be      = (be << (high ? 4 : 0));
[585]1767
[715]1768                size_t tab_index;
1769                if (m_iox_transaction_tab.full(tab_index))
[585]1770                {
[715]1771#ifdef INSTRUMENTATION
1772m_cpt_trt_config_full++;
1773#endif
1774
1775                    // wait for an empty slot in the IOX transaction table.
1776                    // buffer SRCID and TRDID of VCI command to store them
1777                    // later in IOX transaction table.
1778                    r_config_cmd_srcid = p_vci_tgt_int.srcid.read();
1779                    r_config_cmd_trdid = p_vci_tgt_int.trdid.read();
1780                    r_config_cmd_fsm   = CONFIG_CMD_WAIT;
1781                    break;
[585]1782                }
[715]1783
1784                // TRDID in IOX interconnect is the translation table index
1785                r_config_cmd_trdid = tab_index;
1786
1787                // create new entry in IOX transaction table
1788                m_iox_transaction_tab.set( tab_index,
1789                        p_vci_tgt_int.srcid.read(),
1790                        p_vci_tgt_int.trdid.read());
1791
1792                if (eop) r_config_cmd_fsm = CONFIG_CMD_PUT;
1793                else     r_config_cmd_fsm = CONFIG_CMD_HI;
1794
1795#if DEBUG_CONFIG_CMD
1796if( m_debug_activated )
1797{
1798std::cout << name()
[763]1799          << "  <IOB CONFIG_CMD_IDLE> New entry in IOX transaction table"
[715]1800          << std::endl;
1801m_iox_transaction_tab.printTrace();
1802}
1803#endif
1804
[240]1805            }
[715]1806            else if ( eop )                                   // out of segment address
[451]1807            {
[715]1808                r_config_cmd_to_config_rsp_rerror = true;
[712]1809                r_config_cmd_to_config_rsp_rdata  = 0;
[715]1810                r_config_cmd_to_config_rsp_rsrcid = p_vci_tgt_int.srcid.read();
1811                r_config_cmd_to_config_rsp_rtrdid = p_vci_tgt_int.trdid.read();
1812                r_config_cmd_to_config_rsp_rpktid = p_vci_tgt_int.pktid.read();
1813                r_config_cmd_fsm                  = CONFIG_CMD_RSP;
[451]1814            }
[434]1815        } // end if cmdval
[240]1816        break;
1817    }
[585]1818    /////////////////////
[715]1819    case CONFIG_CMD_WAIT:
[240]1820    {
[715]1821        // wait for an empty slot in the translation table.
1822        size_t tab_index;
1823        if (m_iox_transaction_tab.full(tab_index))
[585]1824        {
[715]1825#ifdef INSTRUMENTATION
1826m_cpt_trt_config_full_cost++;
1827#endif
1828            break;
1829        }
1830
1831        // create new entry in IOX transaction table
1832        m_iox_transaction_tab.set( tab_index,
1833                r_config_cmd_srcid.read(),
1834                r_config_cmd_trdid.read());
1835
1836        // TRDID in IOX interconnect is the translation table index
1837        r_config_cmd_trdid = tab_index;
1838        if (r_config_cmd_eop.read()) r_config_cmd_fsm = CONFIG_CMD_PUT;
1839        else                         r_config_cmd_fsm = CONFIG_CMD_HI;
1840
1841#if DEBUG_CONFIG_CMD
1842if( m_debug_activated )
1843{
1844std::cout << name()
[763]1845          << "  <IOB CONFIG_CMD_WAIT> New entry in IOX transaction table"
[715]1846          << std::endl;
1847m_iox_transaction_tab.printTrace();
1848}
1849#endif
1850        break;
1851    }
1852    /////////////////////
1853    case CONFIG_CMD_HI:  // consume the second flit for a multi-flits write
1854    {
1855        if ( p_vci_tgt_int.cmdval.read() )
1856        {
[585]1857            vci_addr_t paddr = p_vci_tgt_int.address.read();
[715]1858            bool       high  = ((paddr & 0x4) == 0x4);
[585]1859            bool       eop   = p_vci_tgt_int.eop.read();
1860
1861            assert( (paddr == r_config_cmd_address.read() + 4) and high and
1862            "ERROR in vci_io_bridge : addresses must be contiguous in write burst" );
1863
1864            r_config_cmd_wdata = r_config_cmd_wdata.read() |
1865                                 ((ext_data_t)p_vci_tgt_int.wdata.read()<<32);
1866            r_config_cmd_be    = r_config_cmd_be.read() |
1867                                 ((ext_be_t)p_vci_tgt_int.be.read()<<4);
1868            r_config_cmd_eop   = eop;
1869            r_config_cmd_fsm   = CONFIG_CMD_PUT;
1870        }
1871        break;
1872    }
[715]1873    /////////////////////
1874    case CONFIG_CMD_LO:  // consume the first flit for a multi-flits write
1875    {
1876        if ( p_vci_tgt_int.cmdval.read() )
1877        {
1878            vci_addr_t paddr = p_vci_tgt_int.address.read();
1879            bool       high  = ((paddr & 0x4) == 0x4);
1880            bool       eop   = p_vci_tgt_int.eop.read();
1881
1882            assert( (paddr == r_config_cmd_address.read() + 4) and !high and
1883            "ERROR in vci_io_bridge : addresses must be contiguous in write burst" );
1884
1885            r_config_cmd_address = p_vci_tgt_int.address.read();
1886            r_config_cmd_wdata   = (ext_data_t)p_vci_tgt_int.wdata.read();
1887            r_config_cmd_be      = (ext_be_t)p_vci_tgt_int.be.read();
1888            r_config_cmd_eop     = eop;
1889
1890            if (eop) r_config_cmd_fsm = CONFIG_CMD_PUT;
1891            else     r_config_cmd_fsm = CONFIG_CMD_HI;
1892        }
1893        break;
1894    }
[585]1895    ////////////////////
[712]1896    case CONFIG_CMD_PUT:   // post a command to CONFIG_CMD fifo (to IOX network)
[585]1897    {
[434]1898        config_cmd_fifo_put = true;
1899
[585]1900        if ( m_config_cmd_addr_fifo.wok() )
[240]1901        {
[434]1902
1903#if DEBUG_CONFIG_CMD
[715]1904if( m_debug_activated )
1905std::cout << name()
1906          << "  <IOB CONFIG_CMD_PUT> Transmit VCI command to IOX network"
[585]1907          << " : address = " << std::hex << r_config_cmd_address.read()
[715]1908          << " / srcid = " << m_iox_srcid
1909          << " / trdid = " << r_config_cmd_trdid.read()
[585]1910          << " / eop = " << r_config_cmd_eop.read()
[434]1911          << std::endl;
1912#endif
[715]1913            if (r_config_cmd_eop.read()) r_config_cmd_fsm = CONFIG_CMD_IDLE;
1914            else                         r_config_cmd_fsm = CONFIG_CMD_LO;
[434]1915        }
1916        break;
[240]1917    }
[585]1918    ////////////////////
[715]1919    case CONFIG_CMD_RSP:   // Post a request to CONFIG_RSP FSM,
[712]1920                           // if no previous pending request.
1921                           // r_config_cmd_to_config_rsp_rerror
[715]1922                           // has been set in IDLE state.
[240]1923    {
[712]1924        if ( not r_config_cmd_to_config_rsp_req.read() )
[240]1925        {
[712]1926            r_config_cmd_to_config_rsp_req = true;
[434]1927
1928#if DEBUG_CONFIG_CMD
[715]1929if( m_debug_activated )
1930std::cout << name()
1931          << "  <IOB CONFIG_CMD_RSP> Request a response to CONFIG_RSP FSM"
[712]1932          << " / error = " << r_config_cmd_to_config_rsp_rerror.read() << std::endl;
[434]1933#endif
[712]1934            r_config_cmd_fsm = CONFIG_CMD_IDLE;
[240]1935        }
1936        break;
1937    }
1938    } // end switch CONFIG_CMD FSM
1939
1940    //////////////////////////////////////////////////////////////////////////////
[712]1941    // The CONFIG_RSP_FSM controls access to the CONFIG_RSP FIFO to INT network.
1942    // It implements a round robin priority between 2 clients FSMs :
1943    // - CONFIG_CMD : response to a local config command.
1944    // - CONFIG_RSP : responses from peripherals on IOX network
[715]1945    // Regarding the responses from IOX network it handles both single flit
1946    // config responses, and multi-flits read responses (ROM), where data must
1947    // be serialised (64 bits -> 32 bits).
[585]1948    // Note: We use the VCI RPKTID field to distinguish between read cached
1949    // (multi-flits response) and others (single flit response).
1950    // The VCI response flit is only consumed in the PUT_UNC or PUT_HI states.
[434]1951    //////////////////////////////////////////////////////////////////////////////
1952
[712]1953    // does nothing if FIFO full
1954    if ( m_config_rsp_rerror_fifo.wok() )
[240]1955    {
[715]1956        switch( r_config_rsp_fsm.read() )
[712]1957        {
1958            /////////////////////////
1959            case CONFIG_RSP_IDLE_IOX:  // IOX requests have highest priority
1960                                       // no flit on IOX network is consumed
[715]1961            {
[712]1962                if ( p_vci_ini_iox.rspval.read() )  // IOX request
[715]1963                {
1964                    // recover srcid and trdid from the IOX transaction table
1965                    size_t tab_index = (size_t)p_vci_ini_iox.rtrdid.read();
1966                    r_config_rsp_rsrcid = m_iox_transaction_tab.readSrcid(tab_index);
1967                    r_config_rsp_rtrdid = m_iox_transaction_tab.readTrdid(tab_index);
1968
1969                    // erase entry
1970                    m_iox_transaction_tab.erase(tab_index);
1971
1972                    if ( (p_vci_ini_iox.rpktid.read() & 0x5) == 0x1 )   // multi-flits
[712]1973                    {
[715]1974                        r_config_rsp_fsm   = CONFIG_RSP_PUT_LO;
[712]1975                    }
[715]1976                    else                                                // single flit
[712]1977                    {
1978                        r_config_rsp_fsm   = CONFIG_RSP_PUT_UNC;
1979                    }
[715]1980#if DEBUG_CONFIG_RSP
1981if( m_debug_activated )
1982{
1983std::cout << name()
[763]1984          << "  <IOB CONFIG_RSP_IDLE_IOX> Remove entry in transaction table"
[715]1985          << std::endl;
1986m_iox_transaction_tab.printTrace();
1987}
1988#endif
1989                }
1990                else if ( r_config_cmd_to_config_rsp_req.read() ) // LOCAL request
[712]1991                {
1992                    r_config_rsp_fsm = CONFIG_RSP_PUT_LOC;
1993                }
[715]1994                break;
[585]1995            }
[712]1996            /////////////////////////
[715]1997            case CONFIG_RSP_IDLE_LOC:  // LOCAL requests have highest priority
[712]1998                                       // no flit on IOX network is consumed
[715]1999            {
2000                if ( r_config_cmd_to_config_rsp_req.read() ) // LOCAL request
[712]2001                {
2002                    r_config_rsp_fsm = CONFIG_RSP_PUT_LOC;
2003                }
2004                else if ( p_vci_ini_iox.rspval.read() ) // IOX request
[715]2005                {
2006                    // recover srcid and trdid from the IOX transaction table
2007                    size_t tab_index = (size_t)p_vci_ini_iox.rtrdid.read();
2008                    r_config_rsp_rsrcid = m_iox_transaction_tab.readSrcid(tab_index);
2009                    r_config_rsp_rtrdid = m_iox_transaction_tab.readTrdid(tab_index);
2010
2011                    // erase entry
2012                    m_iox_transaction_tab.erase(tab_index);
2013
2014                    if ( (p_vci_ini_iox.rpktid.read() & 0x5) == 0x1 )   // multi-flits
[712]2015                    {
[715]2016                        r_config_rsp_fsm   = CONFIG_RSP_PUT_LO;
[712]2017                    }
[715]2018                    else                                                // single flit
[712]2019                    {
2020                        r_config_rsp_fsm   = CONFIG_RSP_PUT_UNC;
2021                    }
[715]2022#if DEBUG_CONFIG_RSP
2023if( m_debug_activated )
2024{
2025std::cout << name()
[763]2026          << "  <IOB CONFIG_RSP_IDLE_IOX> Remove entry in transaction table"
[715]2027          << std::endl;
2028m_iox_transaction_tab.printTrace();
2029}
2030#endif
2031                }
2032                break;
[712]2033            }
2034            ////////////////////////
[715]2035            case CONFIG_RSP_PUT_LO:   // put 32 low bits into CONFIG_RSP fifo
[712]2036                                       // no flit on IOX network is consumed
[585]2037            {
[712]2038                config_rsp_fifo_put    = true;
2039                config_rsp_fifo_rerror = p_vci_ini_iox.rerror.read();
2040                config_rsp_fifo_rdata  = (uint32_t)p_vci_ini_iox.rdata.read();
[715]2041                config_rsp_fifo_rsrcid = r_config_rsp_rsrcid.read();
2042                config_rsp_fifo_rtrdid = r_config_rsp_rtrdid.read();
[712]2043                config_rsp_fifo_rpktid = p_vci_ini_iox.rpktid.read();
2044                config_rsp_fifo_reop   = false;
[240]2045
[712]2046                r_config_rsp_fsm   = CONFIG_RSP_PUT_HI;
2047
[585]2048#if DEBUG_CONFIG_RSP
[715]2049if( m_debug_activated )
2050std::cout << name()
2051          << "  <IOB CONFIG_RSP_PUT_LO> Push multi-flit response into CONFIG_RSP FIFO"
2052          << " / rsrcid = " << std::hex << r_config_rsp_rsrcid.read()
2053          << " / rtrdid = " << r_config_rsp_rtrdid.read()
[585]2054          << " / rpktid = " << p_vci_ini_iox.rpktid.read()
2055          << " / rdata = " << (uint32_t)p_vci_ini_iox.rdata.read()
2056          << " / reop  = " << false
2057          << " / rerror = " << p_vci_ini_iox.rerror.read() << std::endl;
2058#endif
[715]2059                break;
[712]2060            }
2061            ///////////////////////
2062            case CONFIG_RSP_PUT_HI:    // put 32 high bits into CONFIG_RSP fifo
[715]2063                                   // flit on IOX network is consumed
[712]2064            {
2065                config_rsp_fifo_put    = true;
2066                config_rsp_fifo_rerror = p_vci_ini_iox.rerror.read();
2067                config_rsp_fifo_rdata  = (uint32_t)(p_vci_ini_iox.rdata.read() >> 32);
[715]2068                config_rsp_fifo_rsrcid = r_config_rsp_rsrcid.read();
2069                config_rsp_fifo_rtrdid = r_config_rsp_rtrdid.read();
[712]2070                config_rsp_fifo_rpktid = p_vci_ini_iox.rpktid.read();
2071                config_rsp_fifo_reop   = p_vci_ini_iox.reop.read();
[434]2072
[712]2073                if( p_vci_ini_iox.reop.read() ) r_config_rsp_fsm = CONFIG_RSP_IDLE_LOC;
[715]2074                else                            r_config_rsp_fsm = CONFIG_RSP_PUT_LO;
[712]2075
[240]2076#if DEBUG_CONFIG_RSP
[715]2077if( m_debug_activated )
2078std::cout << name()
2079          << "  <IOB CONFIG_RSP_PUT_HI> Push multi-flit response into CONFIG_RSP FIFO"
2080          << " / rsrcid = " << std::hex << r_config_rsp_rsrcid.read()
2081          << " / rtrdid = " << r_config_rsp_rtrdid.read()
[585]2082          << " / rpktid = " << p_vci_ini_iox.rpktid.read()
[712]2083          << " / rdata = " << (uint32_t)(p_vci_ini_iox.rdata.read() >> 32)
[434]2084          << " / reop  = " << p_vci_ini_iox.reop.read()
2085          << " / rerror = " << p_vci_ini_iox.rerror.read() << std::endl;
[240]2086#endif
[715]2087                break;
[712]2088            }
2089            ////////////////////////
2090            case CONFIG_RSP_PUT_UNC:   // put single flit into CONFIG_RSP fifo
[715]2091                                       // flit on IOX network is consumed
[712]2092            {
[715]2093                assert(  p_vci_ini_iox.reop.read() and
[712]2094                "ERROR in vci_io_bridge : a remote config response should be one flit");
[585]2095
[712]2096                config_rsp_fifo_put    = true;
2097                config_rsp_fifo_rerror = p_vci_ini_iox.rerror.read();
2098                config_rsp_fifo_rdata  = (uint32_t)p_vci_ini_iox.rdata.read();
[715]2099                config_rsp_fifo_rsrcid = r_config_rsp_rsrcid.read();
2100                config_rsp_fifo_rtrdid = r_config_rsp_rtrdid.read();
[712]2101                config_rsp_fifo_rpktid = p_vci_ini_iox.rpktid.read();
2102                config_rsp_fifo_reop   = true;
2103
2104                // update priority
2105                r_config_rsp_fsm   = CONFIG_RSP_IDLE_LOC;
2106
[585]2107#if DEBUG_CONFIG_RSP
[715]2108if( m_debug_activated )
2109std::cout << name()
2110          << "  <IOB CONFIG_RSP_PUT_UNC> Push single flit response into CONFIG_RSP FIFO"
2111          << " / rsrcid = " << std::hex << r_config_rsp_rsrcid.read()
2112          << " / rtrdid = " << r_config_rsp_rtrdid.read()
[585]2113          << " / rpktid = " << p_vci_ini_iox.rpktid.read()
2114          << " / rdata = " << (uint32_t)p_vci_ini_iox.rdata.read()
2115          << " / reop  = " << true
2116          << " / rerror = " << p_vci_ini_iox.rerror.read() << std::endl;
2117#endif
[715]2118                break;
[712]2119            }
2120            ////////////////////////
2121            case CONFIG_RSP_PUT_LOC:   // put single flit into CONFIG_RSP fifo
[715]2122                                       // no flit on IOX network is consumed
[712]2123            {
2124                config_rsp_fifo_put    = true;
2125                config_rsp_fifo_rerror = r_config_cmd_to_config_rsp_rerror.read();
2126                config_rsp_fifo_rdata  = r_config_cmd_to_config_rsp_rdata.read();
[715]2127                config_rsp_fifo_rsrcid = r_config_cmd_to_config_rsp_rsrcid.read();
2128                config_rsp_fifo_rtrdid = r_config_cmd_to_config_rsp_rtrdid.read();
2129                config_rsp_fifo_rpktid = r_config_cmd_to_config_rsp_rpktid.read();
[712]2130                config_rsp_fifo_reop   = true;
[240]2131
[715]2132                // acknowledge request
[712]2133                r_config_cmd_to_config_rsp_req = false;
[240]2134
[712]2135                // update priority
2136                r_config_rsp_fsm   = CONFIG_RSP_IDLE_IOX;
2137
2138#if DEBUG_CONFIG_RSP
[715]2139if( m_debug_activated )
2140std::cout << name()
2141          << "  <IOB CONFIG_RSP_PUT_UNC> Push single flit response into CONFIG_RSP FIFO"
2142          << " / rsrcid = " << std::hex << r_config_cmd_to_config_rsp_rsrcid.read()
2143          << " / rtrdid = " << r_config_cmd_to_config_rsp_rtrdid.read()
2144          << " / rpktid = " << r_config_cmd_to_config_rsp_rpktid.read()
[712]2145          << " / rdata = "  << r_config_cmd_to_config_rsp_rdata.read()
2146          << " / reop  = "  << true
2147          << " / rerror = " << r_config_cmd_to_config_rsp_rerror.read() << std::endl;
2148#endif
[715]2149                break;
[712]2150            }
2151        } // end switch CONFIG_RSP FSM
2152    } // end if FIFO full
2153
[434]2154    ///////////////////////////////////////////////////////////////////////////////////
[712]2155    // The MISS_WTI_CMD component is a combinational switch that push one single flit
2156    // VCI command in the MISS_WTI FIFO to INT Network, depending on two clients :
2157    // 1. MISS requests from TLB_MISS FSM :
2158    //    These requests have highest priority because a TLB MISS is a blocking event
2159    //    for the DMA FSM. The r_tlb_to_miss_wti_cmd_req flip-flop is reset by the
2160    //    MISS_WTI_RSP FSM only when the response is received.
2161    // 2. WTI requests from DMA_CMD FSM :
[715]2162    //    These requestsare non blocking events, and the r_dma_cmd_to_miss_wti_cmd_req
2163    //    flip-flop is reset as soon as the WTI command has been sent.
[712]2164    //    There is two types of WTI requests:
2165    //    - external WTI from peripherals on IOX network.
2166    //    - internal WTI caused by illegal DMA requests.
[240]2167    ////////////////////////////////////////////////////////////////////////////////////
[715]2168
2169    if ( r_tlb_to_miss_wti_cmd_req.read() and
[712]2170         m_miss_wti_cmd_addr_fifo.wok() )                   // put MISS READ
[240]2171    {
[984]2172        r_tlb_to_miss_wti_cmd_req = false;
2173
[712]2174        miss_wti_cmd_fifo_put     = true;
[984]2175        miss_wti_cmd_fifo_address = r_tlb_paddr.read() & CACHE_LINE_MASK;
[715]2176        miss_wti_cmd_fifo_wdata   = 0;
[712]2177        miss_wti_cmd_fifo_cmd     = vci_param_int::CMD_READ;
2178        miss_wti_cmd_fifo_pktid   = PKTID_MISS;
2179        miss_wti_cmd_fifo_srcid   = m_int_srcid;
2180        miss_wti_cmd_fifo_trdid   = 0;
[1022]2181        miss_wti_cmd_fifo_plen    = (vci_plen_t)m_words * vci_param_int::B;
[240]2182
[712]2183#if DEBUG_MISS_WTI_CMD
[434]2184if( m_debug_activated )
[715]2185std::cout << name()
2186          << "  <IOB MISS_WTI_CMD_WTI> push MISS TLB command into MISS_WTI FIFO"
[984]2187          << " / PADDR = " << std::hex << miss_wti_cmd_fifo_address << std::dec
2188          << std::endl;
[434]2189#endif
[240]2190
[712]2191    }
[715]2192    else if ( r_dma_cmd_to_miss_wti_cmd_req.read() and
[712]2193              m_miss_wti_cmd_addr_fifo.wok() )               // put WTI READ / WRITE
2194    {
2195        r_dma_cmd_to_miss_wti_cmd_req = false;
2196
2197        miss_wti_cmd_fifo_put     = true;
2198        miss_wti_cmd_fifo_cmd     = r_dma_cmd_to_miss_wti_cmd_cmd.read();
2199        miss_wti_cmd_fifo_address = r_dma_cmd_to_miss_wti_cmd_addr.read();
2200        miss_wti_cmd_fifo_wdata   = r_dma_cmd_to_miss_wti_cmd_wdata.read();
2201        miss_wti_cmd_fifo_srcid   = r_dma_cmd_to_miss_wti_cmd_srcid.read();
2202        miss_wti_cmd_fifo_trdid   = r_dma_cmd_to_miss_wti_cmd_trdid.read();
2203        miss_wti_cmd_fifo_pktid   = r_dma_cmd_to_miss_wti_cmd_pktid.read();
[1022]2204        miss_wti_cmd_fifo_plen    = (vci_plen_t)vci_param_int::B;
[712]2205
2206#if DEBUG_MISS_WTI_CMD
[434]2207if( m_debug_activated )
[715]2208std::cout << name()
2209          << "  <IOB MISS_WTI_CMD_WTI> push WTI command into MISS_WTI FIFO"
[712]2210          << " / CMD = " << miss_wti_cmd_fifo_cmd
[984]2211          << " / PADDR = " << std::hex << miss_wti_cmd_fifo_address << std::dec
2212          << std::endl;
[240]2213#endif
[434]2214
[715]2215    }
[712]2216
[434]2217    ///////////////////////////////////////////////////////////////////////////////////
[712]2218    // The MISS_WTI_RSP FSM handles VCI responses from the INT network:
2219    // - for a TLB MISS (multi-flits read transaction), the cache line
[715]2220    //   is written in r_tlb_buf_data[], and r_tlb_to_miss_wti_cmd_req flip-flop is reset.
[712]2221    // - for a WTI_IOX (single flit write transaction), the response must be
2222    //   forwarded to the source peripheral on the INT network
2223    // - for a WTI_MMU (single flit write transaction), there is nothing to do.
2224    //
[715]2225    // TODO VCI addressing errors for TLB MISS or for WTI_MMU (i.e. kernel errors...)
[712]2226    // are registered in the r_miss_wti_rsp_error_miss & r_miss_wti_rsp_error_wti
2227    // flip-flops, and simulation stops... They could be signaled to OS by a WTI.
[434]2228    ////////////////////////////////////////////////////////////////////////////////////
[715]2229
2230    switch ( r_miss_wti_rsp_fsm.read() )
[434]2231    {
[712]2232        ///////////////////////
[434]2233        case MISS_WTI_RSP_IDLE:   // waiting a VCI response
[712]2234                                  // no VCI flit is consumed
[240]2235        {
[715]2236            if ( p_vci_ini_int.rspval.read() )
[240]2237            {
[715]2238                if ( p_vci_ini_int.rpktid.read() == PKTID_WTI_IOX )
[240]2239                {
[712]2240                    r_miss_wti_rsp_fsm   = MISS_WTI_RSP_WTI_IOX;
2241                }
[715]2242                else if ( p_vci_ini_int.rpktid.read() == PKTID_WTI_MMU )
[712]2243                {
2244                    r_miss_wti_rsp_fsm   = MISS_WTI_RSP_WTI_MMU;
2245                }
2246                else if ( p_vci_ini_int.rpktid.read() == PKTID_MISS )
2247                {
[434]2248                    r_miss_wti_rsp_fsm   = MISS_WTI_RSP_MISS;
2249                    r_miss_wti_rsp_count = 0;
[240]2250                }
[712]2251                else
[434]2252                {
[712]2253                    assert ( false and
2254                    "VCI_IO_BRIDGE ERROR : illegal response type on INT network");
[434]2255                }
[240]2256            }
2257            break;
2258        }
[712]2259        //////////////////////////
2260        case MISS_WTI_RSP_WTI_IOX:   // Handling response to a peripheral WTI
2261                                     // consume VCI flit and transfer response
2262                                     // to DMA_RSP FSM in dedicated registers
2263                                     // if no pending previous request.
[240]2264        {
[715]2265            assert( p_vci_ini_int.reop.read() and
2266            "VCI_IO_BRIDGE ERROR: WTI_IOX response should have one single flit" );
2267
[712]2268            if ( not r_miss_wti_rsp_to_dma_rsp_req.read() ) // no previous pending request
2269            {
2270                r_miss_wti_rsp_to_dma_rsp_req    = true;
2271                r_miss_wti_rsp_to_dma_rsp_rerror = p_vci_ini_int.rerror.read();
2272                r_miss_wti_rsp_to_dma_rsp_rsrcid = p_vci_ini_int.rsrcid.read();
2273                r_miss_wti_rsp_to_dma_rsp_rtrdid = p_vci_ini_int.rtrdid.read();
2274                r_miss_wti_rsp_to_dma_rsp_rpktid = p_vci_ini_int.rpktid.read();
[240]2275
[712]2276                r_miss_wti_rsp_fsm = MISS_WTI_RSP_IDLE;
[434]2277
[712]2278#if DEBUG_MISS_WTI_RSP
[434]2279if( m_debug_activated )
[715]2280std::cout << name()
2281          << "  <IOB MISS_WTI_RSP_WTI_IOX> Transfer response to a WTI_IOX" << std::endl;
[240]2282#endif
[712]2283            }
[240]2284            break;
2285        }
[715]2286        //////////////////////////
[712]2287        case MISS_WTI_RSP_WTI_MMU:   // Handling response to an iommu WTI
2288                                     // consume VCI flit and test VCI error.
2289        {
[715]2290            assert( p_vci_ini_int.reop.read() and
2291            "VCI_IO_BRIDGE ERROR: WTI_MMU response should have one single flit" );
2292
[712]2293            if ( (p_vci_ini_int.rerror.read()&0x1) != 0 )  // error reported
2294            {
2295                // set the specific error flip-flop
2296                r_miss_wti_rsp_error_wti = true;
[715]2297                assert( false and
[712]2298                "VCI_IO_BRIDGE ERROR: VCI error response for a WTI_MMU transaction");
2299            }
2300
2301#if DEBUG_MISS_WTI_RSP
[715]2302if( m_debug_activated )
2303std::cout << name()
2304          << " <IOB MISS_WTI_RSP_WTI_MMU> Receive response to a WTI_MMU" << std::endl;
[712]2305#endif
2306            break;
2307        }
[434]2308        ///////////////////////
[715]2309        case MISS_WTI_RSP_MISS:   // Handling response to a TLB MISS
[712]2310                                  // write cache line in r_tlb_buf buffer
2311                                  // and analyse possible VCI error
2312                                  // VCI flit is consumed.
[240]2313        {
[715]2314            if ( p_vci_ini_int.rspval.read() )
[240]2315            {
[434]2316                if ( (p_vci_ini_int.rerror.read()&0x1) != 0 )  // error reported
[240]2317                {
[712]2318                    // set the specific error flip-flop
2319                    r_miss_wti_rsp_error_miss = true;
[715]2320                    assert( false and
[712]2321                    "VCI_IO_BRIDGE ERROR: VCI error response for a TLB MISS transaction");
2322
[240]2323                }
[434]2324                else                                           // no error
[712]2325                {
[240]2326
[715]2327#if DEBUG_MISS_WTI_CMD
2328if( m_debug_activated )
2329std::cout << name()
2330          << "  <IOB MISS_WTI_RSP_MISS> Receive response to a TLB MISS"
[434]2331          << " / Count = " << r_miss_wti_rsp_count.read()
[715]2332          << " / Data = " << std::hex << p_vci_ini_int.rdata.read() << std::endl;
[240]2333#endif
[712]2334                    r_tlb_buf_data[r_miss_wti_rsp_count.read()] = p_vci_ini_int.rdata.read();
2335                }
[715]2336
[712]2337                if ( p_vci_ini_int.reop.read() )               // last flit
[715]2338                {
[984]2339                    assert((r_miss_wti_rsp_count.read() == (m_words-1)) and
[434]2340                    "VCI_IO_BRIDGE ERROR: invalid length for a TLB MISS response");
[240]2341
[984]2342                    r_miss_wti_rsp_count       = 0;
2343                    r_miss_wti_rsp_fsm         = MISS_WTI_RSP_IDLE;
2344                    r_miss_wti_rsp_to_tlb_done = true;
[712]2345                }
[715]2346                else                                           // not the last flit
[712]2347                {
[434]2348                    r_miss_wti_rsp_count = r_miss_wti_rsp_count.read() + 1;
[240]2349                }
2350            }
2351            break;
2352        }
[434]2353    } // end  switch r_miss_wti_rsp_fsm
[240]2354
[434]2355
2356    ///////////////////////////////////////////////////////////
2357    // DMA_CMD fifo update
[712]2358    // writer : DMA_CMD FSM
[434]2359    ///////////////////////////////////////////////////////////
2360
2361    m_dma_cmd_addr_fifo.update(   dma_cmd_fifo_get,
2362                                  dma_cmd_fifo_put,
2363                                  r_dma_cmd_paddr.read() );   // address translation
2364    m_dma_cmd_cmd_fifo.update(    dma_cmd_fifo_get,
2365                                  dma_cmd_fifo_put,
2366                                  p_vci_tgt_iox.cmd.read() );
2367    m_dma_cmd_contig_fifo.update( dma_cmd_fifo_get,
2368                                  dma_cmd_fifo_put,
2369                                  p_vci_tgt_iox.contig.read() );
2370    m_dma_cmd_cons_fifo.update(   dma_cmd_fifo_get,
2371                                  dma_cmd_fifo_put,
2372                                  p_vci_tgt_iox.cons.read() );
2373    m_dma_cmd_plen_fifo.update(   dma_cmd_fifo_get,
2374                                  dma_cmd_fifo_put,
2375                                  p_vci_tgt_iox.plen.read() );
2376    m_dma_cmd_wrap_fifo.update(   dma_cmd_fifo_get,
2377                                  dma_cmd_fifo_put,
2378                                  p_vci_tgt_iox.wrap.read() );
2379    m_dma_cmd_cfixed_fifo.update( dma_cmd_fifo_get,
2380                                  dma_cmd_fifo_put,
2381                                  p_vci_tgt_iox.cfixed.read() );
2382    m_dma_cmd_clen_fifo.update(   dma_cmd_fifo_get,
2383                                  dma_cmd_fifo_put,
2384                                  p_vci_tgt_iox.clen.read() );
2385    m_dma_cmd_srcid_fifo.update(  dma_cmd_fifo_get,
2386                                  dma_cmd_fifo_put,
[715]2387                                  dma_cmd_fifo_srcid );
[434]2388    m_dma_cmd_trdid_fifo.update(  dma_cmd_fifo_get,
2389                                  dma_cmd_fifo_put,
2390                                  p_vci_tgt_iox.trdid.read() );
2391    m_dma_cmd_pktid_fifo.update(  dma_cmd_fifo_get,
2392                                  dma_cmd_fifo_put,
2393                                  p_vci_tgt_iox.pktid.read() );
2394    m_dma_cmd_data_fifo.update(   dma_cmd_fifo_get,
2395                                  dma_cmd_fifo_put,
[715]2396                                  p_vci_tgt_iox.wdata.read() );
[434]2397    m_dma_cmd_be_fifo.update(     dma_cmd_fifo_get,
2398                                  dma_cmd_fifo_put,
[715]2399                                  p_vci_tgt_iox.be.read() );
[434]2400    m_dma_cmd_eop_fifo.update(    dma_cmd_fifo_get,
2401                                  dma_cmd_fifo_put,
2402                                  p_vci_tgt_iox.eop.read() );
2403
2404    //////////////////////////////////////////////////////////////
2405    // DMA_RSP fifo update
[712]2406    // writer : DMA_RSP FSM
[434]2407    //////////////////////////////////////////////////////////////
2408
[712]2409    m_dma_rsp_data_fifo.update(   dma_rsp_fifo_get,
2410                                  dma_rsp_fifo_put,
2411                                  dma_rsp_fifo_rdata );
2412    m_dma_rsp_rsrcid_fifo.update( dma_rsp_fifo_get,
2413                                  dma_rsp_fifo_put,
[715]2414                                  dma_rsp_fifo_rsrcid );
[712]2415    m_dma_rsp_rtrdid_fifo.update( dma_rsp_fifo_get,
2416                                  dma_rsp_fifo_put,
[715]2417                                  dma_rsp_fifo_rtrdid );
[712]2418    m_dma_rsp_rpktid_fifo.update( dma_rsp_fifo_get,
2419                                  dma_rsp_fifo_put,
[715]2420                                  dma_rsp_fifo_rpktid );
[712]2421    m_dma_rsp_reop_fifo.update(   dma_rsp_fifo_get,
2422                                  dma_rsp_fifo_put,
[715]2423                                  dma_rsp_fifo_reop );
[712]2424    m_dma_rsp_rerror_fifo.update( dma_rsp_fifo_get,
2425                                  dma_rsp_fifo_put,
2426                                  dma_rsp_fifo_rerror );
[240]2427
[434]2428    ////////////////////////////////////////////////////////////////
2429    // CONFIG_CMD fifo update
[712]2430    // writer : CONFIG_CMD FSM
[434]2431    ////////////////////////////////////////////////////////////////
2432
2433    m_config_cmd_addr_fifo.update(   config_cmd_fifo_get,
2434                                     config_cmd_fifo_put,
[715]2435                                     r_config_cmd_address.read() );
[434]2436    m_config_cmd_cmd_fifo.update(    config_cmd_fifo_get,
2437                                     config_cmd_fifo_put,
[715]2438                                     r_config_cmd_cmd.read() );
[240]2439    m_config_cmd_contig_fifo.update( config_cmd_fifo_get,
[434]2440                                     config_cmd_fifo_put,
[715]2441                                     r_config_cmd_contig.read() );
[434]2442    m_config_cmd_cons_fifo.update(   config_cmd_fifo_get,
2443                                     config_cmd_fifo_put,
[715]2444                                     r_config_cmd_cons.read() );
[434]2445    m_config_cmd_plen_fifo.update(   config_cmd_fifo_get,
2446                                     config_cmd_fifo_put,
[715]2447                                     r_config_cmd_plen.read() );
[434]2448    m_config_cmd_wrap_fifo.update(   config_cmd_fifo_get,
2449                                     config_cmd_fifo_put,
[715]2450                                     r_config_cmd_wrap.read() );
[240]2451    m_config_cmd_cfixed_fifo.update( config_cmd_fifo_get,
[434]2452                                     config_cmd_fifo_put,
[715]2453                                     r_config_cmd_cfixed.read() );
[434]2454    m_config_cmd_clen_fifo.update(   config_cmd_fifo_get,
2455                                     config_cmd_fifo_put,
[715]2456                                     r_config_cmd_clen.read() );
[434]2457    m_config_cmd_trdid_fifo.update(  config_cmd_fifo_get,
2458                                     config_cmd_fifo_put,
[585]2459                                     r_config_cmd_trdid.read() );
[434]2460    m_config_cmd_pktid_fifo.update(  config_cmd_fifo_get,
2461                                     config_cmd_fifo_put,
[585]2462                                     r_config_cmd_pktid.read() );
[434]2463    m_config_cmd_data_fifo.update(   config_cmd_fifo_get,
2464                                     config_cmd_fifo_put,
[585]2465                                     r_config_cmd_wdata.read() );
[434]2466    m_config_cmd_be_fifo.update(     config_cmd_fifo_get,
2467                                     config_cmd_fifo_put,
[585]2468                                     r_config_cmd_be.read() );
[434]2469    m_config_cmd_eop_fifo.update(    config_cmd_fifo_get,
2470                                     config_cmd_fifo_put,
[585]2471                                     r_config_cmd_eop.read() );
[715]2472
[434]2473    //////////////////////////////////////////////////////////////////////////
2474    // CONFIG_RSP fifo update
[712]2475    // writer : CONFIG_RSP FSM
[434]2476    //////////////////////////////////////////////////////////////////////////
2477
[712]2478    m_config_rsp_data_fifo.update(   config_rsp_fifo_get,
2479                                     config_rsp_fifo_put,
[715]2480                                     config_rsp_fifo_rdata );
[712]2481    m_config_rsp_rsrcid_fifo.update( config_rsp_fifo_get,
2482                                     config_rsp_fifo_put,
2483                                     config_rsp_fifo_rsrcid );
2484    m_config_rsp_rtrdid_fifo.update( config_rsp_fifo_get,
2485                                     config_rsp_fifo_put,
2486                                     config_rsp_fifo_rtrdid );
2487    m_config_rsp_rpktid_fifo.update( config_rsp_fifo_get,
2488                                     config_rsp_fifo_put,
2489                                     config_rsp_fifo_rpktid );
2490    m_config_rsp_reop_fifo.update(   config_rsp_fifo_get,
2491                                     config_rsp_fifo_put,
2492                                     config_rsp_fifo_reop );
2493    m_config_rsp_rerror_fifo.update( config_rsp_fifo_get,
2494                                     config_rsp_fifo_put,
2495                                     config_rsp_fifo_rerror );
[715]2496
[712]2497    ////////////////////////////////////////////////////////////////
2498    // MISS_WTI_CMD fifo update
2499    // One writer : MISS_WTI switch
2500    ////////////////////////////////////////////////////////////////
[585]2501
[712]2502    m_miss_wti_cmd_addr_fifo.update(   miss_wti_cmd_fifo_get,
2503                                       miss_wti_cmd_fifo_put,
[715]2504                                       miss_wti_cmd_fifo_address );
[712]2505    m_miss_wti_cmd_cmd_fifo.update(    miss_wti_cmd_fifo_get,
2506                                       miss_wti_cmd_fifo_put,
[715]2507                                       miss_wti_cmd_fifo_cmd );
[712]2508    m_miss_wti_cmd_contig_fifo.update( config_cmd_fifo_get,
2509                                       miss_wti_cmd_fifo_put,
2510                                       true );
2511    m_miss_wti_cmd_cons_fifo.update(   miss_wti_cmd_fifo_get,
2512                                       miss_wti_cmd_fifo_put,
2513                                       false );
2514    m_miss_wti_cmd_plen_fifo.update(   miss_wti_cmd_fifo_get,
2515                                       miss_wti_cmd_fifo_put,
[984]2516                                       miss_wti_cmd_fifo_plen );
[712]2517    m_miss_wti_cmd_wrap_fifo.update(   miss_wti_cmd_fifo_get,
2518                                       miss_wti_cmd_fifo_put,
2519                                       false );
2520    m_miss_wti_cmd_cfixed_fifo.update( config_cmd_fifo_get,
2521                                       miss_wti_cmd_fifo_put,
2522                                       false );
2523    m_miss_wti_cmd_clen_fifo.update(   miss_wti_cmd_fifo_get,
2524                                       miss_wti_cmd_fifo_put,
2525                                       0 );
2526    m_miss_wti_cmd_srcid_fifo.update(  miss_wti_cmd_fifo_get,
2527                                       miss_wti_cmd_fifo_put,
2528                                       miss_wti_cmd_fifo_srcid );
2529    m_miss_wti_cmd_trdid_fifo.update(  miss_wti_cmd_fifo_get,
2530                                       miss_wti_cmd_fifo_put,
2531                                       miss_wti_cmd_fifo_trdid );
2532    m_miss_wti_cmd_pktid_fifo.update(  miss_wti_cmd_fifo_get,
2533                                       miss_wti_cmd_fifo_put,
2534                                       miss_wti_cmd_fifo_pktid );
2535    m_miss_wti_cmd_data_fifo.update(   miss_wti_cmd_fifo_get,
2536                                       miss_wti_cmd_fifo_put,
2537                                       miss_wti_cmd_fifo_wdata );
2538    m_miss_wti_cmd_be_fifo.update(     miss_wti_cmd_fifo_get,
2539                                       miss_wti_cmd_fifo_put,
2540                                       0xF );
2541    m_miss_wti_cmd_eop_fifo.update(    miss_wti_cmd_fifo_get,
2542                                       miss_wti_cmd_fifo_put,
2543                                       true );
[715]2544
[240]2545} // end transition()
2546
[712]2547//////////////////////////////////////////////////////////////////////////
[240]2548tmpl(void)::genMoore()
[712]2549//////////////////////////////////////////////////////////////////////////
[240]2550{
[712]2551    /////////////////  p_vci_ini_ram  /////////////////////////////
2552
[434]2553    // VCI initiator command on RAM network
2554    // directly the content of the dma_cmd FIFO
[715]2555    p_vci_ini_ram.cmdval  = m_dma_cmd_addr_fifo.rok();
[434]2556    p_vci_ini_ram.address = m_dma_cmd_addr_fifo.read();
2557    p_vci_ini_ram.be      = m_dma_cmd_be_fifo.read();
2558    p_vci_ini_ram.cmd     = m_dma_cmd_cmd_fifo.read();
2559    p_vci_ini_ram.contig  = m_dma_cmd_contig_fifo.read();
[715]2560    p_vci_ini_ram.wdata   = m_dma_cmd_data_fifo.read();
[434]2561    p_vci_ini_ram.eop     = m_dma_cmd_eop_fifo.read();
2562    p_vci_ini_ram.cons    = m_dma_cmd_cons_fifo.read();
2563    p_vci_ini_ram.plen    = m_dma_cmd_plen_fifo.read();
2564    p_vci_ini_ram.wrap    = m_dma_cmd_wrap_fifo.read();
2565    p_vci_ini_ram.cfixed  = m_dma_cmd_cfixed_fifo.read();
2566    p_vci_ini_ram.clen    = m_dma_cmd_clen_fifo.read();
2567    p_vci_ini_ram.trdid   = m_dma_cmd_trdid_fifo.read();
2568    p_vci_ini_ram.pktid   = m_dma_cmd_pktid_fifo.read();
2569    p_vci_ini_ram.srcid   = m_dma_cmd_srcid_fifo.read();
[715]2570
[712]2571    // VCI initiator response on the RAM Network
2572    // depends on the DMA_RSP FSM state
[715]2573    p_vci_ini_ram.rspack = m_dma_rsp_data_fifo.wok() and
2574                           (r_dma_rsp_fsm.read() == DMA_RSP_PUT_DMA);
[240]2575
[712]2576    /////////////////  p_vci_tgt_iox  /////////////////////////////
[240]2577
[712]2578    // VCI target response on IOX network is
[434]2579    // directly the content of the DMA_RSP FIFO
2580    p_vci_tgt_iox.rspval  = m_dma_rsp_data_fifo.rok();
2581    p_vci_tgt_iox.rsrcid  = m_dma_rsp_rsrcid_fifo.read();
2582    p_vci_tgt_iox.rtrdid  = m_dma_rsp_rtrdid_fifo.read();
2583    p_vci_tgt_iox.rpktid  = m_dma_rsp_rpktid_fifo.read();
[715]2584    p_vci_tgt_iox.rdata   = m_dma_rsp_data_fifo.read();
[434]2585    p_vci_tgt_iox.rerror  = m_dma_rsp_rerror_fifo.read();
2586    p_vci_tgt_iox.reop    = m_dma_rsp_reop_fifo.read();
[240]2587
[712]2588    // VCI target command ack on IOX network
2589    // depends on the DMA_CMD FSM state
[715]2590    switch ( r_dma_cmd_fsm.read() )
[712]2591    {
[715]2592        case DMA_CMD_IDLE:
2593             p_vci_tgt_iox.cmdack  = false;
[712]2594             break;
2595        case DMA_CMD_DMA_REQ:
[715]2596             p_vci_tgt_iox.cmdack  = m_dma_cmd_addr_fifo.wok();
[712]2597             break;
2598        case DMA_CMD_WTI_IOX_REQ:
[715]2599             p_vci_tgt_iox.cmdack  = not r_dma_cmd_to_miss_wti_cmd_req.read();
[712]2600             break;
2601        case DMA_CMD_ERR_WTI_REQ:
[715]2602             p_vci_tgt_iox.cmdack  = false;
[712]2603             break;
[715]2604        case DMA_CMD_ERR_WAIT_EOP:
2605             p_vci_tgt_iox.cmdack  = true;
[712]2606             break;
[715]2607        case DMA_CMD_ERR_RSP_REQ:
2608             p_vci_tgt_iox.cmdack  = false;
[712]2609             break;
[715]2610        case DMA_CMD_TLB_MISS_WAIT:
2611             p_vci_tgt_iox.cmdack  = false;
[712]2612             break;
2613    }
[240]2614
[712]2615    //////////////////  p_vci_ini_iox  /////////////////////////////
[240]2616
[712]2617    // VCI initiator command on IOX network is
[434]2618    // directly the content of the CONFIG_CMD FIFO
2619    p_vci_ini_iox.cmdval  = m_config_cmd_addr_fifo.rok();
2620    p_vci_ini_iox.address = m_config_cmd_addr_fifo.read();
2621    p_vci_ini_iox.be      = m_config_cmd_be_fifo.read();
2622    p_vci_ini_iox.cmd     = m_config_cmd_cmd_fifo.read();
2623    p_vci_ini_iox.contig  = m_config_cmd_contig_fifo.read();
[715]2624    p_vci_ini_iox.wdata   = m_config_cmd_data_fifo.read();
[434]2625    p_vci_ini_iox.eop     = m_config_cmd_eop_fifo.read();
2626    p_vci_ini_iox.cons    = m_config_cmd_cons_fifo.read();
2627    p_vci_ini_iox.plen    = m_config_cmd_plen_fifo.read();
2628    p_vci_ini_iox.wrap    = m_config_cmd_wrap_fifo.read();
2629    p_vci_ini_iox.cfixed  = m_config_cmd_cfixed_fifo.read();
2630    p_vci_ini_iox.clen    = m_config_cmd_clen_fifo.read();
2631    p_vci_ini_iox.trdid   = m_config_cmd_trdid_fifo.read();
2632    p_vci_ini_iox.pktid   = m_config_cmd_pktid_fifo.read();
[715]2633    p_vci_ini_iox.srcid   = m_iox_srcid;
2634
[712]2635    // VCI initiator response on IOX Network
2636    // it depends on the CONFIG_RSP FSM state
[715]2637    p_vci_ini_iox.rspack = m_config_rsp_data_fifo.wok() and
[712]2638                           ( (r_config_rsp_fsm.read() == CONFIG_RSP_PUT_UNC) or
2639                             (r_config_rsp_fsm.read() == CONFIG_RSP_PUT_HI) );
2640
2641    /////////////////  p_vci_tgt_int  ////////////////////////////////
2642
2643    // VCI target response on INT network
2644    // directly the content of the CONFIG_RSP FIFO
2645    p_vci_tgt_int.rspval  = m_config_rsp_data_fifo.rok();
[715]2646    p_vci_tgt_int.rsrcid  = m_config_rsp_rsrcid_fifo.read();
[712]2647    p_vci_tgt_int.rtrdid  = m_config_rsp_rtrdid_fifo.read();
2648    p_vci_tgt_int.rpktid  = m_config_rsp_rpktid_fifo.read();
2649    p_vci_tgt_int.rdata   = m_config_rsp_data_fifo.read();
2650    p_vci_tgt_int.rerror  = m_config_rsp_rerror_fifo.read();
2651    p_vci_tgt_int.reop    = m_config_rsp_reop_fifo.read();
[715]2652
[434]2653    // VCI target command ack on INT network
[240]2654    // it depends on the CONFIG_CMD FSM state
[715]2655    switch ( r_config_cmd_fsm.read() )
[240]2656    {
2657    case CONFIG_CMD_IDLE:
[715]2658        p_vci_tgt_int.cmdack = true;
[585]2659        break;
[715]2660    case CONFIG_CMD_WAIT:
2661        p_vci_tgt_int.cmdack = false;
[585]2662        break;
[715]2663    case CONFIG_CMD_HI:
2664        p_vci_tgt_int.cmdack = true;
[240]2665        break;
[715]2666    case CONFIG_CMD_LO:
2667        p_vci_tgt_int.cmdack = true;
[240]2668        break;
[715]2669    case CONFIG_CMD_PUT:
2670        p_vci_tgt_int.cmdack = false;
2671        break;
2672    case CONFIG_CMD_RSP:
2673        p_vci_tgt_int.cmdack = false;
2674        break;
[585]2675    }
[240]2676
[712]2677    /////////////////  p_vci_ini_int  ////////////////////////////////
[240]2678
[715]2679    // VCI initiator command  on INT network
2680    // directly the content of the MISS_WTI_CMD FIFO
[712]2681    p_vci_ini_int.cmdval  = m_miss_wti_cmd_addr_fifo.rok();
2682    p_vci_ini_int.address = m_miss_wti_cmd_addr_fifo.read();
2683    p_vci_ini_int.be      = m_miss_wti_cmd_be_fifo.read();
2684    p_vci_ini_int.cmd     = m_miss_wti_cmd_cmd_fifo.read();
2685    p_vci_ini_int.contig  = m_miss_wti_cmd_contig_fifo.read();
[715]2686    p_vci_ini_int.wdata   = m_miss_wti_cmd_data_fifo.read();
[712]2687    p_vci_ini_int.eop     = m_miss_wti_cmd_eop_fifo.read();
2688    p_vci_ini_int.cons    = m_miss_wti_cmd_cons_fifo.read();
2689    p_vci_ini_int.plen    = m_miss_wti_cmd_plen_fifo.read();
2690    p_vci_ini_int.wrap    = m_miss_wti_cmd_wrap_fifo.read();
2691    p_vci_ini_int.cfixed  = m_miss_wti_cmd_cfixed_fifo.read();
2692    p_vci_ini_int.clen    = m_miss_wti_cmd_clen_fifo.read();
2693    p_vci_ini_int.trdid   = m_miss_wti_cmd_trdid_fifo.read();
2694    p_vci_ini_int.pktid   = m_miss_wti_cmd_pktid_fifo.read();
2695    p_vci_ini_int.srcid   = m_miss_wti_cmd_srcid_fifo.read();
[434]2696
2697    // VCI initiator response on INT network
2698    // It depends on the MISS_WTI_RSP FSM state
2699
[712]2700    if ( r_miss_wti_rsp_fsm.read() == MISS_WTI_RSP_IDLE )
2701    {
2702        p_vci_ini_int.rspack = false;
2703    }
2704    else if ( r_miss_wti_rsp_fsm.read() == MISS_WTI_RSP_WTI_IOX )
2705    {
2706        p_vci_ini_int.rspack = not r_miss_wti_rsp_to_dma_rsp_req.read();
2707    }
2708    else  //  MISS_WTI_RSP_MISS or MISS_WTI_RESP_WTI_MMU
2709    {
2710        p_vci_ini_int.rspack = true;
2711    }
[434]2712
[240]2713} // end genMoore
2714
2715}}
2716
2717// Local Variables:
2718// tab-width: 4
2719// c-basic-offset: 4
2720// c-file-offsets:((innamespace . 0)(inline-open . 0))
2721// indent-tabs-mode: nil
2722// End:
2723
2724// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.