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

Last change on this file since 740 was 740, checked in by alain, 10 years ago

Cosmetic

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