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

Last change on this file since 716 was 715, checked in by cfuguet, 10 years ago

vci_io_bridge:

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