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

Last change on this file since 715 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
Line 
1/* -*- c++ -*-
2 * File : vci_io_bridge.cpp
3 * Copyright (c) UPMC, Lip6, SoC
4 * Authors: Cassio Fraga, Alain Greiner
5 *
6 * SOCLIB_LGPL_HEADER_BEGIN
7 *
8 * This file is part of SoCLib, GNU LGPLv2.1.
9 *
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.
13 *
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.
18 *
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
23 *
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
32
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
37//    m_debug_activated = (m_debug_ok) and (m_cpt_cycle > m_debug_start_cycle)
38/////////////////////////////////////////////////////////////////////////////////
39
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
46
47namespace soclib {
48namespace caba {
49
50namespace {
51
52const char *dma_cmd_fsm_state_str[] =
53    {
54        "DMA_CMD_IDLE",
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",
61    };
62
63const char *dma_rsp_fsm_state_str[] =
64    {
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",
71    };
72
73const char *tlb_fsm_state_str[] =
74    {
75        "TLB_IDLE",
76        "TLB_MISS",
77        "TLB_PTE1_GET",
78        "TLB_PTE1_SELECT",
79        "TLB_PTE1_UPDT",
80        "TLB_PTE2_GET",
81        "TLB_PTE2_SELECT",
82        "TLB_PTE2_UPDT",
83        "TLB_WAIT",
84        "TLB_RETURN",
85        "TLB_INVAL_CHECK",
86    };
87
88const char *config_cmd_fsm_state_str[] =
89    {
90        "CONFIG_CMD_IDLE",
91        "CONFIG_CMD_HI",
92        "CONFIG_CMD_LO",
93        "CONFIG_CMD_PUT",
94        "CONFIG_CMD_RSP",
95    };
96
97const char *config_rsp_fsm_state_str[] =
98    {
99        "CONFIG_RSP_IDLE_IOX",
100        "CONFIG_RSP_IDLE_LOC",
101        "CONFIG_RSP_PUT_LO",
102        "CONFIG_RSP_PUT_HI",
103        "CONFIG_RSP_PUT_UNC",
104        "CONFIG_RSP_PUT_LOC",
105    };
106
107const char *miss_wti_rsp_state_str[] =
108    {
109        "MISS_WTI_RSP_IDLE",
110        "MISS_WTI_RSP_WTI_IOX",
111        "MISS_WTI_RSP_WTI_MMU",
112        "MISS_WTI_RSP_MISS",
113    };
114}
115
116#define tmpl(...)  template<typename vci_param_int,typename vci_param_ext> __VA_ARGS__ VciIoBridge<vci_param_int,vci_param_ext>
117
118////////////////////////
119tmpl(/**/)::VciIoBridge(
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
128    const size_t                        dcache_words,
129    const size_t                        iotlb_ways,
130    const size_t                        iotlb_sets,
131    const uint32_t                      debug_start_cycle,
132    const bool                          debug_ok)
133    : soclib::caba::BaseModule(name),
134
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"),
142
143      m_words( dcache_words ),
144
145      // INT & IOX Network
146      m_int_seglist( mt_int.getSegmentList( int_tgtid )),
147      m_int_srcid( mt_int.indexForId( int_srcid )),
148      m_iox_seglist( mt_iox.getSegmentList( iox_tgtid )),
149      m_iox_srcid( mt_iox.indexForId( iox_srcid )),
150
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
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
162      // addressable registers
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"),
168      r_iommu_wti_enable("r_iommu_wti_enable"),
169      r_iommu_wti_addr_lo("r_iommu_wti_addr_lo"),
170
171      // DMA_CMD FSM registers
172      r_dma_cmd_fsm("r_dma_cmd_fsm"),
173      r_dma_cmd_paddr("r_dma_cmd_paddr"),
174
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"),
186
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"),
189
190      //DMA_RSP FSM registers
191      r_dma_rsp_fsm("r_dma_rsp_fsm"),
192
193      // CONFIG_CMD FSM registers
194      r_config_cmd_fsm("r_config_cmd_fsm"),
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"),
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"),
205
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"),
211      r_config_cmd_trdid("r_config_cmd_trdid"),
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"),
220
221      // ID translation table used by CONFIG_CMD and CONFIG_RSP FSMs
222      m_iox_transaction_tab(1),
223
224      // CONFIG_RSP FSM registers
225      r_config_rsp_fsm("r_config_rsp_fsm"),
226      r_config_rsp_rsrcid("r_config_rsp_rsrcid"),
227      r_config_rsp_rtrdid("r_config_rsp_rtrdid"),
228
229      // TLB FSM registers
230      r_tlb_fsm("r_tlb_fsm"),
231      r_waiting_transaction("r_waiting_transaction"),
232      r_tlb_miss_type("r_tlb_miss_type"),
233      r_tlb_miss_error("r_tlb_miss_error"),
234
235      r_tlb_paddr("r_tlb_paddr"),
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"),
239      r_tlb_set("r_tlb_set"),
240
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"),
245
246      r_tlb_to_miss_wti_cmd_req("r_tlb_to_miss_wti_cmd_req"),
247
248      // MISS_WTI_RSP FSM registers
249      r_miss_wti_rsp_fsm("r_miss_wti_rsp_fsm"),
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"),
253
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"),
259
260      // TLB for IOMMU
261      r_iotlb("iotlb", 0, iotlb_ways, iotlb_sets, vci_param_int::N),
262
263      // DMA_CMD FIFOs
264      m_dma_cmd_addr_fifo("m_dma_cmd_addr_fifo",2),
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),
272      m_dma_cmd_eop_fifo("m_dma_cmd_eop_fifo",2),
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),
276      m_dma_cmd_cfixed_fifo("m_dma_cmd_cfixed_fifo",2),
277      m_dma_cmd_clen_fifo("m_dma_cmd_clen_fifo",2),
278
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),
286
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
304      m_config_rsp_data_fifo("m_config_rsp_data_fifo",2),
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),
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)
326{
327    std::cout << "  - Building VciIoBridge : " << name << std::endl;
328
329    // checking segments on INT network
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()
338                  << " / size = " << int_seg->size()
339                  << " / special = " << int_seg->special() << std::endl;
340    }
341
342    // checking segments on IOX network
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()
351                  << " / size = " << iox_seg->size() << std::endl;
352    }
353
354    assert( (vci_param_int::N == vci_param_ext::N) and
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
360    assert( (vci_param_int::B == 4) and
361    "VCI_IO_BRIDGE ERROR: VCI DATA width must be 32 bits on internal network");
362
363    assert( (vci_param_ext::B == 8) and
364    "VCI_IO_BRIDGE ERROR: VCI DATA width must be 64 bits on external network");
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
372    SC_METHOD(transition);
373    dont_initialize();
374    sensitive << p_clk.pos();
375
376    SC_METHOD(genMoore);
377    dont_initialize();
378    sensitive << p_clk.neg();
379
380 }
381
382/////////////////////////////////////
383tmpl(/**/)::~VciIoBridge()
384/////////////////////////////////////
385{
386    delete [] r_tlb_buf_data;
387}
388
389////////////////////////////////////
390tmpl(void)::print_trace(size_t mode)
391////////////////////////////////////
392{
393    // b0 : IOTLB trace
394
395    std::cout << std::dec << "IO_BRIDGE " << name() << std::endl;
396
397    std::cout << "  "  << dma_cmd_fsm_state_str[r_dma_cmd_fsm.read()]
398              << " | " << dma_rsp_fsm_state_str[r_dma_rsp_fsm.read()]
399              << " | " << tlb_fsm_state_str[r_tlb_fsm.read()]
400              << " | " << config_cmd_fsm_state_str[r_config_cmd_fsm.read()]
401              << " | " << config_rsp_fsm_state_str[r_config_rsp_fsm.read()]
402              << " | " << miss_wti_rsp_state_str[r_miss_wti_rsp_fsm.read()]
403              << std::endl;
404
405    if(mode & 0x01)
406    {
407        std::cout << "  IOTLB" << std::endl;
408        r_iotlb.printTrace();
409    }
410
411    if(mode & 0x02)
412    {
413        std::cout << "  IOX TRANSACTION TAB" << std::endl;
414        m_iox_transaction_tab.printTrace();
415    }
416}
417
418////////////////////////
419tmpl(void)::print_stats()
420////////////////////////
421{
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;
432}
433
434////////////////////////
435tmpl(void)::clear_stats()
436////////////////////////
437{
438    m_cpt_iotlb_read                = 0;
439    m_cpt_iotlb_miss                = 0;
440    m_cost_iotlb_miss               = 0;
441    m_cpt_iotlbmiss_transaction     = 0;
442    m_cost_iotlbmiss_transaction    = 0;
443}
444
445////////////////////////////////////
446tmpl(bool)::is_wti(vci_addr_t paddr)
447////////////////////////////////////
448{
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;
457}
458
459/////////////////////////
460tmpl(void)::transition()
461/////////////////////////
462{
463    if ( not p_resetn.read() )
464    {
465        r_dma_cmd_fsm      = DMA_CMD_IDLE;
466        r_dma_rsp_fsm      = DMA_RSP_IDLE_DMA;
467        r_tlb_fsm          = TLB_IDLE;
468        r_config_cmd_fsm   = CONFIG_CMD_IDLE;
469        r_config_rsp_fsm   = CONFIG_RSP_IDLE_IOX;
470        r_miss_wti_rsp_fsm = MISS_WTI_RSP_IDLE;
471
472        r_tlb_buf_valid    = false;
473        r_iommu_active     = false;
474        r_iommu_wti_enable = false;
475
476        // initializing translation table
477        m_iox_transaction_tab.init();
478
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();
494
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();
501
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();
516
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();
531
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();
538
539        // SET/RESET Communication flip-flops
540        r_dma_cmd_to_miss_wti_cmd_req  = false;
541        r_dma_cmd_to_dma_rsp_req       = false;
542        r_dma_cmd_to_tlb_req           = false;
543        r_config_cmd_to_tlb_req        = false;
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;
547
548        // error flip_flops
549        r_miss_wti_rsp_error_miss      = false;
550        r_miss_wti_rsp_error_wti       = false;
551
552        // Debug variable
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
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;
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;
569        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_tlb                [i]   = 0;
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;
572        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_miss_wti_rsp       [i]   = 0;
573
574        return;
575    }
576
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();
580    vci_srcid_t     dma_cmd_fifo_srcid        = 0;
581
582    bool            dma_rsp_fifo_put          = false;
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;
590
591    bool            config_cmd_fifo_put       = false;
592    bool            config_cmd_fifo_get       = p_vci_ini_iox.cmdack.read();
593
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
612#ifdef INSTRUMENTATION
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() ] ++;
618    m_cpt_fsm_miss_wti_rsp      [r_miss_wti_rsp_fsm.read() ] ++;
619#endif
620
621    m_cpt_total_cycles++;
622
623    m_debug_activated  = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;
624
625    //////////////////////////////////////////////////////////////////////////////
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)
639    ///////////////////////////////////////////////////////////////////////////////
640
641    switch( r_dma_cmd_fsm.read() )
642    {
643    //////////////////
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
647    {
648        if ( p_vci_tgt_iox.cmdval.read() )
649        {
650            if ( not r_iommu_active.read() )    // tlb not activated
651            {
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                {
659                    assert( p_vci_tgt_iox.eop.read() and
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
669#if DEBUG_DMA_CMD
670if( m_debug_activated )
671std::cout << name()
672          << "  <IOB DMA_CMD_IDLE> DMA command"
673          << " : address = " << std::hex << p_vci_tgt_iox.address.read()
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;
678#endif
679            }
680            else if (r_tlb_fsm.read() == TLB_IDLE ||
681                     r_tlb_fsm.read() == TLB_WAIT )   // tlb access possible
682            {
683                vci_addr_t  iotlb_paddr;
684                pte_info_t  iotlb_flags;
685                size_t      iotlb_way;
686                size_t      iotlb_set;
687                vci_addr_t  iotlb_nline;
688                bool        iotlb_hit;
689
690#ifdef INSTRUMENTATION
691m_cpt_iotlb_read++;
692#endif
693                iotlb_hit = r_iotlb.translate(p_vci_tgt_iox.address.read(),
694                                              &iotlb_paddr,
695                                              &iotlb_flags,
696                                              &iotlb_nline,  // unused
697                                              &iotlb_way,    // unused
698                                              &iotlb_set );  // unused
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) )
704                    {
705                        // register error
706                        r_iommu_etr      = MMU_WRITE_ACCES_VIOLATION;
707                        r_iommu_bvar     = p_vci_tgt_iox.address.read();
708                        r_iommu_bad_id   = p_vci_tgt_iox.srcid.read();
709
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;
717#if DEBUG_DMA_CMD
718if( m_debug_activated )
719std::cout << name()
720          << "  <IOB DMA_CMD_IDLE> TLB HIT but writable violation" << std::endl;
721#endif
722                    }
723                    else                         // no access rights violation
724                    {
725#if DEBUG_DMA_CMD
726if( m_debug_activated )
727std::cout << name()
728          << "  <IOB DMA_CMD_IDLE> TLB HIT" << std::endl;
729#endif
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                        {
736                            assert( p_vci_tgt_iox.eop.read() and
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
740                            r_dma_cmd_fsm = DMA_CMD_WTI_IOX_REQ;
741                        }
742                        else
743                        {
744                            r_dma_cmd_fsm = DMA_CMD_DMA_REQ;
745                        }
746                    }
747                }
748                else                                             // TLB miss
749                {
750
751#ifdef INSTRUMENTATION
752m_cpt_iotlb_miss++;
753#endif
754                    // register virtual address, and send request to TLB FSM
755                    r_dma_cmd_to_tlb_vaddr = p_vci_tgt_iox.address.read();
756                    r_dma_cmd_to_tlb_req   = true;
757                    r_dma_cmd_fsm          = DMA_CMD_TLB_MISS_WAIT;
758#if DEBUG_DMA_CMD
759if( m_debug_activated )
760std::cout << name()
761          << "  <IOB DMA_CMD_IDLE> TLB MISS" << std::endl;
762#endif
763                } // end tlb miss
764            } // end if tlb_activated
765        } // end if cmdval
766        break;
767    }
768    /////////////////////
769    case DMA_CMD_DMA_REQ:    // put a flit in DMA_CMD FIFO
770                             // if contig, VCI address must be incremented
771                             // after initial translation by IOMMU.
772                             // flit is consumed if DMA_CMD FIFO not full
773    {
774        if ( p_vci_tgt_iox.cmdval && m_dma_cmd_addr_fifo.wok() )
775        {
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");
780
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
795#if DEBUG_DMA_CMD
796if( m_debug_activated )
797std::cout << name()
798          << "  <IOB DMA_CMD_FIFO_PUT_CMD> Push into DMA_CMD fifo:"
799          << " address = " << std::hex << r_dma_cmd_paddr.read()
800          << " srcid = " << dma_cmd_fifo_srcid
801          << " wdata = " << p_vci_tgt_iox.wdata.read()
802          << " plen = " << std::dec << p_vci_tgt_iox.plen.read()
803          << " eop = " << std::dec << p_vci_tgt_iox.eop.read() << std::endl;
804#endif
805        }
806        break;
807    }
808    /////////////////////////
809    case DMA_CMD_WTI_IOX_REQ:    // post a WTI_IOX request to MISS_WTI FSM
810                                 // if no prending previous request
811                                 // command arguments are stored in dedicated registers
812                                 // VCI flit is consumed if no previous request
813    {
814        if ( not r_dma_cmd_to_miss_wti_cmd_req.read() )  // no previous pending request
815        {
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
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();
828            r_dma_cmd_to_miss_wti_cmd_srcid = wti_srcid;
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;
833
834#if DEBUG_DMA_CMD
835if( m_debug_activated )
836std::cout << name()
837          << "  <IOB DMA_CMD_WTI_IOX_REQ> request WTI transaction from ext peripheral"
838          << " : address = " << std::hex << r_dma_cmd_paddr.read()
839          << " / srcid = " << wti_srcid
840          << " / wdata = " << p_vci_tgt_iox.wdata.read() << std::endl;
841#endif
842        }
843        break;
844    }
845    //////////////////////////
846    case DMA_CMD_ERR_WAIT_EOP:   // wait EOP before requesting WTI & error response
847                                 // VCI flit is always consumed
848    {
849        if ( p_vci_tgt_iox.eop.read() ) r_dma_cmd_fsm = DMA_CMD_ERR_WTI_REQ;
850
851#if DEBUG_DMA_CMD
852if( m_debug_activated )
853std::cout << name()
854          << "  <IOB DMA_CMD_WAIT_EOP> wait EOP for faulty DMA command" << std::endl;
855#endif
856        break;
857    }
858
859    /////////////////////////
860    case DMA_CMD_ERR_WTI_REQ:    // post a WTI_MMU request to MISS_WTI_CMD FSM
861                                 // if no prending previous request
862                                 // response arguments are stored in dedicated registers
863                                 // no VCI flit is consumed
864    {
865        if ( not r_dma_cmd_to_miss_wti_cmd_req.read() )  // no pending previous request
866        {
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;
874
875            r_dma_cmd_fsm            = DMA_CMD_ERR_RSP_REQ;
876
877#if DEBUG_DMA_CMD
878if( m_debug_activated )
879std::cout << name()
880          << "  <IOB DMA_CMD_ERR_WTI_REQ> request an IOMMU WTI" << std::endl;
881#endif
882        }
883        break;
884    }
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
889                                 // no VCI flit is consumed
890    {
891        if ( not r_dma_cmd_to_dma_rsp_req.read() )  // no pending previous request
892        {
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
901                                 // we must test a possible page fault error...
902    {
903        if ( not r_dma_cmd_to_tlb_req.read() ) // TLB miss completed
904        {
905            if ( r_tlb_miss_error.read() )   // Error reported by TLB FSM
906            {
907                r_iommu_etr     = MMU_READ_PT2_UNMAPPED;
908                r_iommu_bvar    = r_dma_cmd_to_tlb_vaddr.read();
909                r_iommu_bad_id  = p_vci_tgt_iox.srcid.read();
910                r_dma_cmd_fsm   = DMA_CMD_ERR_WAIT_EOP;
911            }
912            else                            // No error
913            {
914                r_dma_cmd_fsm   = DMA_CMD_IDLE;
915            }
916        }
917        break;
918    }
919    } // end switch DMA_CMD FSM
920
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    ////////////////////////////////////////////////////////////////////////////////
930
931    // does nothing if FIFO is full
932    if ( m_dma_rsp_rerror_fifo.wok() )
933    {
934        switch( r_dma_rsp_fsm.read() )
935        {
936            //////////////////////
937            case DMA_RSP_IDLE_DMA:  // normal DMA response has highest priority
938            {
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
946            {
947                if     (r_miss_wti_rsp_to_dma_rsp_req.read()) r_dma_rsp_fsm = DMA_RSP_PUT_WTI;
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
954            {
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;
957                else if(r_miss_wti_rsp_to_dma_rsp_req.read()) r_dma_rsp_fsm = DMA_RSP_PUT_WTI;
958                break;
959            }
960            ///////////////////////
961            case DMA_RSP_PUT_DMA:  // put one flit of the DMA response into FIFO
962            {
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();
966                dma_rsp_fifo_rsrcid = m_srcid_lid_mask[p_vci_ini_ram.rsrcid.read()];
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();
970
971                // update priority
972                if ( p_vci_ini_ram.reop.read() ) r_dma_rsp_fsm = DMA_RSP_IDLE_WTI;
973
974#if DEBUG_DMA_RSP
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()]
980          << " / rtrdid = " << p_vci_ini_ram.rtrdid.read()
981          << " / rpktid = " << p_vci_ini_ram.rpktid.read()
982          << " / rdata = "  << p_vci_ini_ram.rdata.read()
983          << " / rerror = " << p_vci_ini_ram.rerror.read()
984          << " / reop = "   << p_vci_ini_ram.reop.read() << std::endl;
985#endif
986                break;
987            }
988            ///////////////////////
989            case DMA_RSP_PUT_WTI:  // put single flit WTI response into FIFO
990            {
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;
994                dma_rsp_fifo_rsrcid = 
995                    m_srcid_lid_mask[r_miss_wti_rsp_to_dma_rsp_rsrcid.read()];
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;
999
1000                // acknowledge request
1001                r_miss_wti_rsp_to_dma_rsp_req = false;
1002
1003                // update priority
1004                r_dma_rsp_fsm = DMA_RSP_IDLE_ERR;
1005
1006#if DEBUG_DMA_RSP
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()]
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;
1033
1034                // update priority
1035                r_dma_rsp_fsm = DMA_RSP_PUT_DMA;
1036
1037#if DEBUG_DMA_RSP
1038if( m_debug_activated )
1039std::cout << name()
1040          << "  <IOB DMA_RSP_PUT_DMA> Push IOMMU ERROR response into DMA_RSP FIFO"
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            }
1050        } // end switch DMA_RSP FSM
1051    }  // end if FIFO full
1052
1053
1054    //////////////////////////////////////////////////////////////////////////////////
1055    // The TLB FSM handles the TLB miss requests from DMA_CMD FSM,
1056    // and the PTE inval request (from CONFIG_CMD FSM).
1057    // PTE inval request have highest priority. In case of TLB miss,
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.
1060    // It bypass the first level page table access if possible.
1061    // It reset the r_dma_cmd_to_tlb_req flip-flop to signal TLB miss completion.
1062    // An unexpected, but possible page fault is signaled in r_tlb_miss_error flip_flop.
1063    ////////////////////////////////////////////////////////////////////////////////////
1064
1065    switch (r_tlb_fsm.read())
1066    {
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
1070    {
1071        if ( r_config_cmd_to_tlb_req.read() ) // Request for a PTE invalidation
1072        {
1073            r_config_cmd_to_tlb_req  = false;
1074            r_waiting_transaction    = false;
1075            r_tlb_fsm                = TLB_INVAL_CHECK;
1076        }
1077
1078        else if ( r_dma_cmd_to_tlb_req.read() )   // request for a TLB Miss
1079        {
1080            // Checking prefetch buffer
1081            if( not r_tlb_buf_big_page )     // small page => PTE2
1082            {
1083                if( r_tlb_buf_valid &&         // Hit on prefetch buffer
1084                    (r_tlb_buf_vaddr.read() ==
1085                    (r_dma_cmd_to_tlb_vaddr.read()& ~PTE2_LINE_OFFSET & ~K_PAGE_OFFSET_MASK)))
1086                {
1087                    size_t   pte_offset = (r_dma_cmd_to_tlb_vaddr.read()& PTE2_LINE_OFFSET)>>12;
1088                    uint32_t pte_flags  = r_tlb_buf_data[2*pte_offset];
1089                    uint32_t pte_ppn    = r_tlb_buf_data[2*pte_offset+1];
1090
1091                    // Bit valid checking
1092                    if ( not ( pte_flags & PTE_V_MASK) )    // unmapped
1093                    {
1094                        std::cout << "VCI_IO_BRIDGE ERROR : " << name()
1095                                  << " Page Table entry unmapped" << std::endl;
1096
1097                        r_tlb_miss_error = true;
1098                        r_dma_cmd_to_tlb_req    = false;
1099#if DEBUG_TLB_MISS
1100if ( m_debug_activated )
1101std::cout << name()
1102          << "  <IOB TLB_IDLE> PTE2 Unmapped" << std::hex
1103          << " / paddr = " << r_tlb_paddr.read()
1104          << " / PTE_FLAGS = " << pte_flags
1105          << " / PTE_PPN = " << pte_ppn << std::endl;
1106#endif
1107                        break;
1108                    }
1109
1110                    // valid PTE2 : we must update the TLB
1111                    r_tlb_pte_flags = pte_flags;
1112                    r_tlb_pte_ppn   = pte_ppn;
1113                    r_tlb_fsm       = TLB_PTE2_SELECT;
1114#if DEBUG_TLB_MISS
1115if ( m_debug_activated )
1116std::cout << name()
1117          << "  <IOB TLB_IDLE> Hit on prefetch buffer: PTE2" << std::hex
1118          << " / PTE_FLAGS = " << pte_flags
1119          << " / PTE_PPN = " << pte_ppn << std::endl;
1120#endif
1121                    break;
1122                }
1123            }
1124            else                             // big page => PTE1
1125            {
1126                if( r_tlb_buf_valid &&         // Hit on prefetch buffer
1127                    (r_tlb_buf_vaddr.read() ==
1128                    (r_dma_cmd_to_tlb_vaddr.read()& ~PTE1_LINE_OFFSET & ~M_PAGE_OFFSET_MASK )))
1129                {
1130                    size_t   pte_offset = (r_dma_cmd_to_tlb_vaddr.read()& PTE1_LINE_OFFSET)>>21;
1131                    uint32_t pte_flags  = r_tlb_buf_data[pte_offset];
1132
1133                    // Bit valid checking
1134                    if ( not ( pte_flags & PTE_V_MASK) )    // unmapped
1135                    {
1136                        std::cout << "VCI_IO_BRIDGE ERROR : " << name()
1137                                  << " Page Table entry unmapped" << std::endl;
1138
1139                        r_tlb_miss_error = true;
1140                        r_dma_cmd_to_tlb_req    = false;
1141#if DEBUG_TLB_MISS
1142if ( m_debug_activated )
1143std::cout << name()
1144          << "  <IOB TLB_IDLE> PTE1 Unmapped" << std::hex
1145          << " / paddr = " << r_tlb_paddr.read()
1146          << " / PTE = " << pte_flags << std::endl;
1147#endif
1148                        break;
1149                    }
1150
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 )
1156std::cout << name()
1157          << "  <IOB TLB_PTE1_GET> Hit on prefetch buffer: PTE1" << std::hex
1158          << " / paddr = " << r_tlb_paddr.read()
1159          << std::hex << " / PTE1 = " << pte_flags << std::endl;
1160#endif
1161                    break;
1162                }
1163            }
1164
1165            // prefetch buffer miss
1166            r_tlb_fsm = TLB_MISS;
1167
1168#if DEBUG_TLB_MISS
1169if ( m_debug_activated )
1170std::cout << name()
1171          << "  <IOB TLB_IDLE> Miss on prefetch buffer"
1172          << std::hex << " / vaddr = " << r_dma_cmd_to_tlb_vaddr.read() << std::endl;
1173#endif
1174        }
1175        break;
1176    }
1177    //////////////
1178    case TLB_MISS: // handling tlb miss
1179    {
1180        uint32_t    ptba = 0;
1181        bool        bypass;
1182        vci_addr_t  pte_paddr;
1183
1184#ifdef INSTRUMENTATION
1185m_cpt_iotlbmiss_transaction++;
1186#endif
1187        // evaluate bypass in order to skip first level page table access
1188        bypass = r_iotlb.get_bypass(r_dma_cmd_to_tlb_vaddr.read(), &ptba);
1189
1190        // Request MISS_WTI_FSM a transaction on INT Network
1191        if ( not bypass )     // Read PTE1/PTD1 in XRAM
1192        {
1193
1194#if DEBUG_TLB_MISS
1195if ( m_debug_activated )
1196std::cout << name()
1197          << "  <IOB TLB_MISS> Read PTE1/PTD1 in memory" << std::endl;
1198#endif
1199            pte_paddr = (vci_addr_t)((r_iommu_ptpr.read()) << (INDEX1_NBITS+2)) |
1200                        (vci_addr_t)((r_dma_cmd_to_tlb_vaddr.read() >> PAGE_M_NBITS) << 2);
1201            r_tlb_paddr = pte_paddr;
1202
1203            r_tlb_to_miss_wti_cmd_req = true;
1204            r_tlb_miss_type           = PTE1_MISS;
1205            r_tlb_fsm                 = TLB_WAIT;
1206        }
1207        else                  // Read PTE2 in XRAM
1208        {
1209
1210#if DEBUG_TLB_MISS
1211if ( m_debug_activated )
1212std::cout << name()
1213          << "  <IOB TLB_MISS> Read PTE2 in memory" << std::endl;
1214#endif
1215            //&PTE2 = PTBA + IX2 * 8
1216            pte_paddr = (vci_addr_t)ptba << PAGE_K_NBITS |
1217                        (vci_addr_t)(r_dma_cmd_to_tlb_vaddr.read()&PTD_ID2_MASK)>>(PAGE_K_NBITS-3);
1218
1219            r_tlb_paddr = pte_paddr;
1220
1221            r_tlb_to_miss_wti_cmd_req = true;
1222            r_tlb_miss_type           = PTE2_MISS;
1223            r_tlb_fsm                 = TLB_WAIT;
1224        }
1225
1226        break;
1227    }
1228    //////////////////
1229    case TLB_PTE1_GET:  // Try to read a PT1 entry in the miss buffer
1230    {
1231
1232        uint32_t  entry;
1233
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 );
1236
1237        // Hit test. Just to verify.
1238        // Hit must happen, since we've just finished its' miss transaction
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
1242        entry = r_tlb_buf_data[word_position];
1243
1244        // Bit valid checking
1245        if ( not ( entry & PTE_V_MASK) )    // unmapped
1246        {
1247            //must not occur!
1248            std::cout << "IOMMU ERROR " << name() << "TLB_IDLE state" << std::endl
1249                      << "The Page Table entry ins't valid (unmapped)" << std::endl;
1250
1251            r_tlb_miss_error       = true;
1252            r_dma_cmd_to_tlb_req   = false;
1253            r_tlb_fsm              = TLB_IDLE;
1254
1255#if DEBUG_TLB_MISS
1256if ( m_debug_activated )
1257{
1258    std::cout << name()
1259              << "  <IOB DMA_PTE1_GET> First level entry Unmapped"
1260              << std::hex << " / paddr = " << r_tlb_paddr.read()
1261              << std::hex << " / PTE = " << entry << std::endl;
1262}
1263#endif
1264                    break;
1265        }
1266
1267        if( entry & PTE_T_MASK )    //  PTD : me must access PT2
1268        {
1269            // register bypass
1270            r_iotlb.set_bypass( r_dma_cmd_to_tlb_vaddr.read(),
1271                                entry & ((1 << (vci_param_int::N-PAGE_K_NBITS)) - 1),
1272                                0); //nline, unused
1273
1274            // &PTE2 = PTBA + IX2 * 8
1275            // ps: PAGE_K_NBITS corresponds also to the size of a second level page table
1276            r_tlb_paddr = (vci_addr_t)(entry & ((1<<(vci_param_int::N-PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
1277                                (vci_addr_t)(((r_dma_cmd_to_tlb_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
1278
1279            r_tlb_to_miss_wti_cmd_req = true;
1280            r_tlb_miss_type           = PTE2_MISS;
1281            r_tlb_fsm                 = TLB_WAIT;
1282
1283#ifdef INSTRUMENTATION
1284m_cpt_iotlbmiss_transaction++;
1285#endif
1286
1287#if DEBUG_TLB_MISS
1288if ( m_debug_activated )
1289std::cout << name()
1290          << "  <IOB TLB_PTE1_GET> Success. Search PTE2" << std::hex
1291          << " / PADDR = " << r_tlb_paddr.read()
1292          << " / PTD = " << entry << std::endl;
1293#endif
1294        }
1295        else            //  PTE1 :  we must update the IOTLB
1296                        //  Should not occur if working only with small pages
1297        {
1298            r_tlb_pte_flags   = entry;
1299            r_tlb_fsm  = TLB_PTE1_SELECT;
1300
1301#if DEBUG_TLB_MISS
1302if ( m_debug_activated )
1303std::cout << name()
1304          << "  <IOB TLB_PTE1_GET> Success. Big page"
1305          << std::hex << " / paddr = " << r_tlb_paddr.read()
1306          << std::hex << " / PTE1 = " << entry << std::endl;
1307#endif
1308        }
1309        break;
1310    }
1311    /////////////////////
1312    case TLB_PTE1_SELECT:   // select a slot for PTE1
1313    {
1314        size_t  way;
1315        size_t  set;
1316
1317        r_iotlb.select(  r_dma_cmd_to_tlb_vaddr.read(),
1318                        true,  // PTE1
1319                        &way,
1320                        &set );
1321#ifdef INSTRUMENTATION
1322m_cpt_iotlb_read++;
1323#endif
1324
1325#if DEBUG_TLB_MISS
1326if ( m_debug_activated )
1327std::cout << name()
1328          << "  <IOB TLB_PTE1_SELECT> Select a slot in TLB"
1329          << " / way = " << std::dec << way
1330          << " / set = " << set << std::endl;
1331#endif
1332        r_tlb_way = way;
1333        r_tlb_set = set;
1334        r_tlb_fsm     = TLB_PTE1_UPDT;
1335        break;
1336    }
1337    ///////////////////
1338    case TLB_PTE1_UPDT:     // write a new PTE1 in tlb
1339                            // not necessary to treat the L/R bit
1340    {
1341        uint32_t  pte   = r_tlb_pte_flags.read();
1342
1343        r_tlb_paddr = (vci_addr_t)( ((r_tlb_pte_flags.read() & PPN1_MASK) << 21)
1344                        | (r_dma_cmd_to_tlb_vaddr.read()& M_PAGE_OFFSET_MASK) );
1345
1346        // update TLB
1347        r_iotlb.write( true,        // 2M page
1348                      pte,
1349                      0,        // argument unused for a PTE1
1350                      r_dma_cmd_to_tlb_vaddr.read(),
1351                      r_tlb_way.read(),
1352                      r_tlb_set.read(),
1353                      0 );      //we set nline = 0
1354
1355#ifdef INSTRUMENTATION
1356m_cpt_iotlb_write++;
1357#endif
1358
1359#if DEBUG_TLB_MISS
1360if ( m_debug_activated )
1361{
1362std::cout << name()
1363          << "  <IOB TLB_PTE1_UPDT> write PTE1 in TLB"
1364          << " / set = " << std::dec << r_tlb_set.read()
1365          << " / way = " << r_tlb_way.read() << std::endl;
1366r_iotlb.printTrace();
1367}
1368#endif
1369        // next state
1370        r_tlb_fsm = TLB_RETURN; // exit sub-fsm
1371        break;
1372    }
1373    //////////////////
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
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 );
1381
1382
1383        // Hit test. Just to verify.
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");
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
1388        // Bit valid checking
1389        if ( not ( pte_flags & PTE_V_MASK) )    // unmapped
1390        {
1391            //must not occur!
1392            std::cout << "IOMMU ERROR " << name() << "TLB_IDLE state" << std::endl
1393                      << "The Page Table entry ins't valid (unmapped)" << std::endl;
1394
1395            r_tlb_miss_error       = true;
1396            r_dma_cmd_to_tlb_req         = false;
1397            r_tlb_fsm             = TLB_IDLE;
1398
1399#if DEBUG_TLB_MISS
1400if ( m_debug_activated )
1401std::cout << name()
1402          << "  <IOB TLB_PTE2_GET> PTE2 Unmapped" << std::hex
1403          << " / PADDR = " << r_tlb_paddr.read()
1404          << " / PTE = " << pte_flags << std::endl;
1405#endif
1406            break;
1407        }
1408
1409        r_tlb_pte_flags       = pte_flags;
1410        r_tlb_pte_ppn         = pte_ppn;
1411        r_tlb_fsm           = TLB_PTE2_SELECT;
1412
1413#if DEBUG_TLB_MISS
1414if ( m_debug_activated )
1415std::cout << name()
1416          << "  <IOB TLB_PTE2_GET> Mapped" << std::hex
1417          << " / PTE_FLAGS = " << pte_flags
1418          << " / PTE_PPN = " << pte_ppn << std::endl;
1419#endif
1420        break;
1421    }
1422    ////////////////////////////
1423    case TLB_PTE2_SELECT:    // select a slot for PTE2
1424    {
1425        size_t way;
1426        size_t set;
1427
1428        r_iotlb.select( r_dma_cmd_to_tlb_vaddr.read(),
1429                        false,  // PTE2
1430                        &way,
1431                        &set );
1432#ifdef INSTRUMENTATION
1433m_cpt_iotlb_read++;
1434#endif
1435
1436#if DEBUG_TLB_MISS
1437if ( m_debug_activated )
1438std::cout << name()
1439          << "  <IOB TLB_PTE2_SELECT> Select a slot in IOTLB:"
1440          << " way = " << std::dec << way
1441          << " / set = " << set << std::endl;
1442#endif
1443        r_tlb_way = way;
1444        r_tlb_set = set;
1445        r_tlb_fsm     = TLB_PTE2_UPDT;
1446        break;
1447    }
1448    ///////////////////
1449    case TLB_PTE2_UPDT:         // write a new PTE2 in tlb
1450                                // not necessary to treat the L/R bit
1451    {
1452        uint32_t        pte_flags = r_tlb_pte_flags.read();
1453        uint32_t        pte_ppn   = r_tlb_pte_ppn.read();
1454
1455        r_tlb_paddr = (vci_addr_t)( ((r_tlb_pte_ppn.read() & PPN2_MASK) << 12)
1456                        | (r_dma_cmd_to_tlb_vaddr.read()& K_PAGE_OFFSET_MASK) );
1457
1458        // update TLB for a PTE2
1459        r_iotlb.write( false,   // 4K page
1460                       pte_flags,
1461                       pte_ppn,
1462                       r_dma_cmd_to_tlb_vaddr.read(),
1463                       r_tlb_way.read(),
1464                       r_tlb_set.read(),
1465                       0 );     // nline = 0
1466#ifdef INSTRUMENTATION
1467m_cpt_iotlb_write++;
1468#endif
1469
1470#if DEBUG_TLB_MISS
1471if ( m_debug_activated )
1472{
1473std::cout << name()
1474          << "  <IOB TLB_PTE2_UPDT> write PTE2 in IOTLB"
1475          << " / set = " << std::dec << r_tlb_set.read()
1476          << " / way = " << r_tlb_way.read() << std::endl;
1477r_iotlb.printTrace();
1478}
1479#endif
1480        // next state
1481        r_tlb_fsm = TLB_RETURN;
1482        break;
1483    }
1484    //////////////
1485    case TLB_WAIT:   // waiting completion of a miss transaction from MISS_WTI FSM
1486                     // PTE inval request are handled as unmaskable interrupts
1487    {
1488        if ( r_config_cmd_to_tlb_req.read() ) // Request for a PTE invalidation
1489        {
1490            r_config_cmd_to_tlb_req = false;
1491            r_waiting_transaction   = true;
1492            r_tlb_fsm               = TLB_INVAL_CHECK;
1493        }
1494
1495#ifdef INSTRUMENTATION
1496m_cost_iotlbmiss_transaction++;
1497#endif
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            {
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;
1506            }
1507            else if(r_tlb_miss_type == PTE1_MISS)
1508            {
1509                r_tlb_fsm = TLB_PTE1_GET;
1510            }
1511            else
1512            {
1513                r_tlb_fsm = TLB_PTE2_GET;
1514            }
1515        }
1516        break;
1517    }
1518    ////////////////
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
1521    {
1522#if DEBUG_TLB_MISS
1523if ( m_debug_activated )
1524std::cout << name()
1525          << "  <IOB TLB_RETURN> IOTLB MISS completed" << std::endl;
1526#endif
1527        r_dma_cmd_to_tlb_req  = false;
1528        r_tlb_fsm = TLB_IDLE;
1529        break;
1530    }
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
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
1538        if(!r_waiting_transaction.read() && r_tlb_buf_valid)
1539        {
1540            if(!r_tlb_buf_big_page)
1541            {
1542               if( r_tlb_buf_vaddr.read() ==
1543                   (r_config_cmd_to_tlb_vaddr.read()& ~PTE2_LINE_OFFSET) )
1544                // The virtual address corresponds to one entry on the buffer line
1545                {
1546                    r_tlb_buf_valid = false;   //change here for individual invalidation
1547                }
1548            }
1549            else    // First level entries on buffer. Unused if only small pages
1550            {
1551               if( r_tlb_buf_vaddr.read() ==
1552                   (r_config_cmd_to_tlb_vaddr.read()& ~PTE1_LINE_OFFSET) )
1553                // The virtual address corresponds to one entry on the buffer line
1554                {
1555                    r_tlb_buf_valid = false;   //change here for individual invalidation
1556                }
1557            }
1558        }
1559
1560        // Invalidation on IOTLB
1561        r_iotlb.inval(r_config_cmd_to_tlb_vaddr.read());
1562
1563        if(r_waiting_transaction.read()) r_tlb_fsm =TLB_WAIT;
1564        else r_tlb_fsm = TLB_IDLE;
1565        break;
1566    }
1567    } //end switch r_tlb_fsm
1568
1569    ////////////////////////////////////////////////////////////////////////////////
1570    // The CONFIG_CMD_FSM handles the VCI commands from the INT network.
1571    // - it can be single flit config transactions
1572    // - it can be multi-flits data transactions to ROM (read) or FBF (write).
1573    // The write burst transactions must be serialised from 32 to 64 bits width.
1574    // The configuration requests can be local (IO_BRIDGE config registers)
1575    // or remote (config registers of peripherals on IOX network).
1576    // - The local configuration segment is identified by the "special" atribute
1577    //   in the mapping table.
1578    // - All configuration requests are checked against segmentation violation.
1579    // - In case of local config request, or in case of segmentation violation,
1580    //   the FSM send a response request to CONFIG_RSP FSM.
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.
1583    ///////////////////////////////////////////////////////////////////////////////
1584
1585    switch( r_config_cmd_fsm.read() )
1586    {
1587    /////////////////////
1588    case CONFIG_CMD_IDLE:   // A VCI INT command is always consumed in this state
1589    {
1590        if ( p_vci_tgt_int.cmdval.read() )
1591        {
1592
1593#if DEBUG_CONFIG_CMD
1594if( m_debug_activated )
1595std::cout << name()
1596          << "  <IOB CONFIG_CMD_IDLE> ### Config Command received" << std::endl
1597          << "  address = " << std::hex << p_vci_tgt_int.address.read()
1598          << " / srcid = " << p_vci_tgt_int.srcid.read()
1599          << " / trdid = " << p_vci_tgt_int.trdid.read()
1600          << " / pktid = " << p_vci_tgt_int.pktid.read()
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;
1605#endif
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);
1608            uint32_t   cell  = (uint32_t)((paddr & 0x1FF)>>2);
1609            bool       eop   = p_vci_tgt_int.eop.read();
1610            bool       high  = (paddr & 0x4);
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();
1613
1614            // chek segments
1615            std::list<soclib::common::Segment>::iterator seg;
1616            bool found   = false;
1617            bool special = false;
1618            for ( seg = m_int_seglist.begin() ;
1619                  seg != m_int_seglist.end() and not found ; seg++ )
1620            {
1621                if ( seg->contains(paddr) )
1622                {
1623                   found   = true;
1624                   special = seg->special();
1625                }
1626            }
1627
1628            if ( found and special )  // IO_BRIDGE itself
1629            {
1630                bool rerror = false;
1631                int_data_t rdata;
1632
1633                assert( (be == 0xF) and
1634                "ERROR in vci_io_bridge : BE must be 0xF for a config access");
1635
1636                assert( ( eop ) and
1637                "ERROR in vci_io_bridge : local config access must be one flit");
1638
1639                if ( not read && (cell == IOB_IOMMU_PTPR) )       // WRITE PTPR
1640                {
1641                    r_iommu_ptpr = (uint32_t)wdata;
1642                }
1643                else if ( read && (cell == IOB_IOMMU_PTPR) )      // READ PTPR
1644                {
1645                    rdata = r_iommu_ptpr.read();
1646                }
1647                else if( not read && (cell == IOB_WTI_ENABLE))  // WRITE WTI_ENABLE
1648                {
1649                    r_iommu_wti_enable = wdata;
1650                }
1651                else if( read && (cell == IOB_WTI_ENABLE))       // READ WTI ENABLE
1652                {
1653                    rdata = r_iommu_wti_enable.read();
1654                }
1655                else if( read && (cell == IOB_IOMMU_BVAR))        // READ BVAR
1656                {
1657                    rdata = r_iommu_bvar.read();
1658                }
1659                else if( read && (cell == IOB_IOMMU_ETR))          // READ ETR
1660                {
1661                    rdata = r_iommu_etr.read();
1662                }
1663                else if( read && (cell == IOB_IOMMU_BAD_ID))      // READ BAD_ID
1664                {
1665                    rdata = r_iommu_bad_id.read();
1666                }
1667                else if( not read && (cell == IOB_INVAL_PTE))     // WRITE INVAL_PTE
1668                {
1669                    r_config_cmd_to_tlb_req   = true;
1670                    r_config_cmd_to_tlb_vaddr = (uint32_t)wdata;
1671                }
1672                else if( not read && (cell == IOB_WTI_ADDR_LO)) // WRITE WTI_PADDR_LO
1673                {
1674                    r_iommu_wti_addr_lo = (vci_addr_t)wdata;
1675                }
1676                else if( read && (cell == IOB_WTI_ADDR_LO))    // READ WTI_PADDR_LO
1677                {
1678                    rdata = r_iommu_wti_addr_lo.read();
1679                }
1680                else if( not read && (cell == IOB_WTI_ADDR_HI)) // WRITE WTI_PADDR_HI
1681                {
1682                    r_iommu_wti_addr_hi = (vci_addr_t)wdata;
1683                }
1684                else if( read && (cell == IOB_WTI_ADDR_HI))    // READ WTI_PADDR_HI
1685                {
1686                    rdata = r_iommu_wti_addr_hi.read();
1687                }
1688                else   // Error: Wrong address, or invalid operation.
1689                {
1690                    rerror = true;
1691                }
1692                r_config_cmd_to_config_rsp_rerror = rerror;
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;
1698            }
1699            else if ( found )                            // remote peripheral
1700            {
1701                // buffer VCI command
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();
1711                r_config_cmd_eop     = eop;
1712                r_config_cmd_wdata   = (wdata << (high ? 32 : 0));
1713                r_config_cmd_be      = (be << (high ? 4 : 0));
1714
1715                size_t tab_index;
1716                if (m_iox_transaction_tab.full(tab_index))
1717                {
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;
1729                }
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
1752            }
1753            else if ( eop )                                   // out of segment address
1754            {
1755                r_config_cmd_to_config_rsp_rerror = true;
1756                r_config_cmd_to_config_rsp_rdata  = 0;
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;
1761            }
1762        } // end if cmdval
1763        break;
1764    }
1765    /////////////////////
1766    case CONFIG_CMD_WAIT:
1767    {
1768        // wait for an empty slot in the translation table.
1769        size_t tab_index;
1770        if (m_iox_transaction_tab.full(tab_index))
1771        {
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        {
1804            vci_addr_t paddr = p_vci_tgt_int.address.read();
1805            bool       high  = ((paddr & 0x4) == 0x4);
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    }
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    }
1842    ////////////////////
1843    case CONFIG_CMD_PUT:   // post a command to CONFIG_CMD fifo (to IOX network)
1844    {
1845        config_cmd_fifo_put = true;
1846
1847        if ( m_config_cmd_addr_fifo.wok() )
1848        {
1849
1850#if DEBUG_CONFIG_CMD
1851if( m_debug_activated )
1852std::cout << name()
1853          << "  <IOB CONFIG_CMD_PUT> Transmit VCI command to IOX network"
1854          << " : address = " << std::hex << r_config_cmd_address.read()
1855          << " / srcid = " << m_iox_srcid
1856          << " / trdid = " << r_config_cmd_trdid.read()
1857          << " / eop = " << r_config_cmd_eop.read()
1858          << std::endl;
1859#endif
1860            if (r_config_cmd_eop.read()) r_config_cmd_fsm = CONFIG_CMD_IDLE;
1861            else                         r_config_cmd_fsm = CONFIG_CMD_LO;
1862        }
1863        break;
1864    }
1865    ////////////////////
1866    case CONFIG_CMD_RSP:   // Post a request to CONFIG_RSP FSM,
1867                           // if no previous pending request.
1868                           // r_config_cmd_to_config_rsp_rerror
1869                           // has been set in IDLE state.
1870    {
1871        if ( not r_config_cmd_to_config_rsp_req.read() )
1872        {
1873            r_config_cmd_to_config_rsp_req = true;
1874
1875#if DEBUG_CONFIG_CMD
1876if( m_debug_activated )
1877std::cout << name()
1878          << "  <IOB CONFIG_CMD_RSP> Request a response to CONFIG_RSP FSM"
1879          << " / error = " << r_config_cmd_to_config_rsp_rerror.read() << std::endl;
1880#endif
1881            r_config_cmd_fsm = CONFIG_CMD_IDLE;
1882        }
1883        break;
1884    }
1885    } // end switch CONFIG_CMD FSM
1886
1887    //////////////////////////////////////////////////////////////////////////////
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
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).
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.
1898    //////////////////////////////////////////////////////////////////////////////
1899
1900    // does nothing if FIFO full
1901    if ( m_config_rsp_rerror_fifo.wok() )
1902    {
1903        switch( r_config_rsp_fsm.read() )
1904        {
1905            /////////////////////////
1906            case CONFIG_RSP_IDLE_IOX:  // IOX requests have highest priority
1907                                       // no flit on IOX network is consumed
1908            {
1909                if ( p_vci_ini_iox.rspval.read() )  // IOX request
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
1920                    {
1921                        r_config_rsp_fsm   = CONFIG_RSP_PUT_LO;
1922                    }
1923                    else                                                // single flit
1924                    {
1925                        r_config_rsp_fsm   = CONFIG_RSP_PUT_UNC;
1926                    }
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
1938                {
1939                    r_config_rsp_fsm = CONFIG_RSP_PUT_LOC;
1940                }
1941                break;
1942            }
1943            /////////////////////////
1944            case CONFIG_RSP_IDLE_LOC:  // LOCAL requests have highest priority
1945                                       // no flit on IOX network is consumed
1946            {
1947                if ( r_config_cmd_to_config_rsp_req.read() ) // LOCAL request
1948                {
1949                    r_config_rsp_fsm = CONFIG_RSP_PUT_LOC;
1950                }
1951                else if ( p_vci_ini_iox.rspval.read() ) // IOX request
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
1962                    {
1963                        r_config_rsp_fsm   = CONFIG_RSP_PUT_LO;
1964                    }
1965                    else                                                // single flit
1966                    {
1967                        r_config_rsp_fsm   = CONFIG_RSP_PUT_UNC;
1968                    }
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;
1980            }
1981            ////////////////////////
1982            case CONFIG_RSP_PUT_LO:   // put 32 low bits into CONFIG_RSP fifo
1983                                       // no flit on IOX network is consumed
1984            {
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();
1988                config_rsp_fifo_rsrcid = r_config_rsp_rsrcid.read();
1989                config_rsp_fifo_rtrdid = r_config_rsp_rtrdid.read();
1990                config_rsp_fifo_rpktid = p_vci_ini_iox.rpktid.read();
1991                config_rsp_fifo_reop   = false;
1992
1993                r_config_rsp_fsm   = CONFIG_RSP_PUT_HI;
1994
1995#if DEBUG_CONFIG_RSP
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()
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
2006                break;
2007            }
2008            ///////////////////////
2009            case CONFIG_RSP_PUT_HI:    // put 32 high bits into CONFIG_RSP fifo
2010                                   // flit on IOX network is consumed
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);
2015                config_rsp_fifo_rsrcid = r_config_rsp_rsrcid.read();
2016                config_rsp_fifo_rtrdid = r_config_rsp_rtrdid.read();
2017                config_rsp_fifo_rpktid = p_vci_ini_iox.rpktid.read();
2018                config_rsp_fifo_reop   = p_vci_ini_iox.reop.read();
2019
2020                if( p_vci_ini_iox.reop.read() ) r_config_rsp_fsm = CONFIG_RSP_IDLE_LOC;
2021                else                            r_config_rsp_fsm = CONFIG_RSP_PUT_LO;
2022
2023#if DEBUG_CONFIG_RSP
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()
2029          << " / rpktid = " << p_vci_ini_iox.rpktid.read()
2030          << " / rdata = " << (uint32_t)(p_vci_ini_iox.rdata.read() >> 32)
2031          << " / reop  = " << p_vci_ini_iox.reop.read()
2032          << " / rerror = " << p_vci_ini_iox.rerror.read() << std::endl;
2033#endif
2034                break;
2035            }
2036            ////////////////////////
2037            case CONFIG_RSP_PUT_UNC:   // put single flit into CONFIG_RSP fifo
2038                                       // flit on IOX network is consumed
2039            {
2040                assert(  p_vci_ini_iox.reop.read() and
2041                "ERROR in vci_io_bridge : a remote config response should be one flit");
2042
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();
2046                config_rsp_fifo_rsrcid = r_config_rsp_rsrcid.read();
2047                config_rsp_fifo_rtrdid = r_config_rsp_rtrdid.read();
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
2054#if DEBUG_CONFIG_RSP
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()
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
2065                break;
2066            }
2067            ////////////////////////
2068            case CONFIG_RSP_PUT_LOC:   // put single flit into CONFIG_RSP fifo
2069                                       // no flit on IOX network is consumed
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();
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();
2077                config_rsp_fifo_reop   = true;
2078
2079                // acknowledge request
2080                r_config_cmd_to_config_rsp_req = false;
2081
2082                // update priority
2083                r_config_rsp_fsm   = CONFIG_RSP_IDLE_IOX;
2084
2085#if DEBUG_CONFIG_RSP
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()
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
2096                break;
2097            }
2098        } // end switch CONFIG_RSP FSM
2099    } // end if FIFO full
2100
2101    ///////////////////////////////////////////////////////////////////////////////////
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 :
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.
2111    //    There is two types of WTI requests:
2112    //    - external WTI from peripherals on IOX network.
2113    //    - internal WTI caused by illegal DMA requests.
2114    ////////////////////////////////////////////////////////////////////////////////////
2115
2116    if ( r_tlb_to_miss_wti_cmd_req.read() and
2117         m_miss_wti_cmd_addr_fifo.wok() )                   // put MISS READ
2118    {
2119        miss_wti_cmd_fifo_put     = true;
2120        miss_wti_cmd_fifo_address = r_tlb_paddr.read();
2121        miss_wti_cmd_fifo_wdata   = 0;
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;
2126
2127#if DEBUG_MISS_WTI_CMD
2128if( m_debug_activated )
2129std::cout << name()
2130          << "  <IOB MISS_WTI_CMD_WTI> push MISS TLB command into MISS_WTI FIFO"
2131          << " / PADDR = " << miss_wti_cmd_fifo_address << std::endl;
2132#endif
2133
2134    }
2135    else if ( r_dma_cmd_to_miss_wti_cmd_req.read() and
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
2149if( m_debug_activated )
2150std::cout << name()
2151          << "  <IOB MISS_WTI_CMD_WTI> push WTI command into MISS_WTI FIFO"
2152          << " / CMD = " << miss_wti_cmd_fifo_cmd
2153          << " / PADDR = " << miss_wti_cmd_fifo_address << std::endl;
2154#endif
2155
2156    }
2157
2158    ///////////////////////////////////////////////////////////////////////////////////
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
2161    //   is written in r_tlb_buf_data[], and r_tlb_to_miss_wti_cmd_req flip-flop is reset.
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    //
2166    // TODO VCI addressing errors for TLB MISS or for WTI_MMU (i.e. kernel errors...)
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.
2169    ////////////////////////////////////////////////////////////////////////////////////
2170
2171    switch ( r_miss_wti_rsp_fsm.read() )
2172    {
2173        ///////////////////////
2174        case MISS_WTI_RSP_IDLE:   // waiting a VCI response
2175                                  // no VCI flit is consumed
2176        {
2177            if ( p_vci_ini_int.rspval.read() )
2178            {
2179                if ( p_vci_ini_int.rpktid.read() == PKTID_WTI_IOX )
2180                {
2181                    r_miss_wti_rsp_fsm   = MISS_WTI_RSP_WTI_IOX;
2182                }
2183                else if ( p_vci_ini_int.rpktid.read() == PKTID_WTI_MMU )
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                {
2189                    r_miss_wti_rsp_fsm   = MISS_WTI_RSP_MISS;
2190                    r_miss_wti_rsp_count = 0;
2191                }
2192                else
2193                {
2194                    assert ( false and
2195                    "VCI_IO_BRIDGE ERROR : illegal response type on INT network");
2196                }
2197            }
2198            break;
2199        }
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.
2205        {
2206            assert( p_vci_ini_int.reop.read() and
2207            "VCI_IO_BRIDGE ERROR: WTI_IOX response should have one single flit" );
2208
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();
2216
2217                r_miss_wti_rsp_fsm = MISS_WTI_RSP_IDLE;
2218
2219#if DEBUG_MISS_WTI_RSP
2220if( m_debug_activated )
2221std::cout << name()
2222          << "  <IOB MISS_WTI_RSP_WTI_IOX> Transfer response to a WTI_IOX" << std::endl;
2223#endif
2224            }
2225            break;
2226        }
2227        //////////////////////////
2228        case MISS_WTI_RSP_WTI_MMU:   // Handling response to an iommu WTI
2229                                     // consume VCI flit and test VCI error.
2230        {
2231            assert( p_vci_ini_int.reop.read() and
2232            "VCI_IO_BRIDGE ERROR: WTI_MMU response should have one single flit" );
2233
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;
2238                assert( false and
2239                "VCI_IO_BRIDGE ERROR: VCI error response for a WTI_MMU transaction");
2240            }
2241
2242#if DEBUG_MISS_WTI_RSP
2243if( m_debug_activated )
2244std::cout << name()
2245          << " <IOB MISS_WTI_RSP_WTI_MMU> Receive response to a WTI_MMU" << std::endl;
2246#endif
2247            break;
2248        }
2249        ///////////////////////
2250        case MISS_WTI_RSP_MISS:   // Handling response to a TLB MISS
2251                                  // write cache line in r_tlb_buf buffer
2252                                  // and analyse possible VCI error
2253                                  // VCI flit is consumed.
2254        {
2255            if ( p_vci_ini_int.rspval.read() )
2256            {
2257                if ( (p_vci_ini_int.rerror.read()&0x1) != 0 )  // error reported
2258                {
2259                    // set the specific error flip-flop
2260                    r_miss_wti_rsp_error_miss = true;
2261                    assert( false and
2262                    "VCI_IO_BRIDGE ERROR: VCI error response for a TLB MISS transaction");
2263
2264                }
2265                else                                           // no error
2266                {
2267
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"
2272          << " / Count = " << r_miss_wti_rsp_count.read()
2273          << " / Data = " << std::hex << p_vci_ini_int.rdata.read() << std::endl;
2274#endif
2275                    r_tlb_buf_data[r_miss_wti_rsp_count.read()] = p_vci_ini_int.rdata.read();
2276                }
2277
2278                if ( p_vci_ini_int.reop.read() )               // last flit
2279                {
2280                    bool eop = p_vci_ini_int.eop.read();
2281                    assert(((eop == (r_miss_wti_rsp_count.read() == (m_words-1)))) and
2282                    "VCI_IO_BRIDGE ERROR: invalid length for a TLB MISS response");
2283
2284                    r_miss_wti_rsp_count      = 0;
2285                    r_miss_wti_rsp_fsm        = MISS_WTI_RSP_IDLE;
2286                    r_tlb_to_miss_wti_cmd_req = false;
2287                }
2288                else                                           // not the last flit
2289                {
2290                    r_miss_wti_rsp_count = r_miss_wti_rsp_count.read() + 1;
2291                }
2292            }
2293            break;
2294        }
2295    } // end  switch r_miss_wti_rsp_fsm
2296
2297
2298    ///////////////////////////////////////////////////////////
2299    // DMA_CMD fifo update
2300    // writer : DMA_CMD FSM
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,
2329                                  dma_cmd_fifo_srcid );
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,
2338                                  p_vci_tgt_iox.wdata.read() );
2339    m_dma_cmd_be_fifo.update(     dma_cmd_fifo_get,
2340                                  dma_cmd_fifo_put,
2341                                  p_vci_tgt_iox.be.read() );
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
2348    // writer : DMA_RSP FSM
2349    //////////////////////////////////////////////////////////////
2350
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,
2356                                  dma_rsp_fifo_rsrcid );
2357    m_dma_rsp_rtrdid_fifo.update( dma_rsp_fifo_get,
2358                                  dma_rsp_fifo_put,
2359                                  dma_rsp_fifo_rtrdid );
2360    m_dma_rsp_rpktid_fifo.update( dma_rsp_fifo_get,
2361                                  dma_rsp_fifo_put,
2362                                  dma_rsp_fifo_rpktid );
2363    m_dma_rsp_reop_fifo.update(   dma_rsp_fifo_get,
2364                                  dma_rsp_fifo_put,
2365                                  dma_rsp_fifo_reop );
2366    m_dma_rsp_rerror_fifo.update( dma_rsp_fifo_get,
2367                                  dma_rsp_fifo_put,
2368                                  dma_rsp_fifo_rerror );
2369
2370    ////////////////////////////////////////////////////////////////
2371    // CONFIG_CMD fifo update
2372    // writer : CONFIG_CMD FSM
2373    ////////////////////////////////////////////////////////////////
2374
2375    m_config_cmd_addr_fifo.update(   config_cmd_fifo_get,
2376                                     config_cmd_fifo_put,
2377                                     r_config_cmd_address.read() );
2378    m_config_cmd_cmd_fifo.update(    config_cmd_fifo_get,
2379                                     config_cmd_fifo_put,
2380                                     r_config_cmd_cmd.read() );
2381    m_config_cmd_contig_fifo.update( config_cmd_fifo_get,
2382                                     config_cmd_fifo_put,
2383                                     r_config_cmd_contig.read() );
2384    m_config_cmd_cons_fifo.update(   config_cmd_fifo_get,
2385                                     config_cmd_fifo_put,
2386                                     r_config_cmd_cons.read() );
2387    m_config_cmd_plen_fifo.update(   config_cmd_fifo_get,
2388                                     config_cmd_fifo_put,
2389                                     r_config_cmd_plen.read() );
2390    m_config_cmd_wrap_fifo.update(   config_cmd_fifo_get,
2391                                     config_cmd_fifo_put,
2392                                     r_config_cmd_wrap.read() );
2393    m_config_cmd_cfixed_fifo.update( config_cmd_fifo_get,
2394                                     config_cmd_fifo_put,
2395                                     r_config_cmd_cfixed.read() );
2396    m_config_cmd_clen_fifo.update(   config_cmd_fifo_get,
2397                                     config_cmd_fifo_put,
2398                                     r_config_cmd_clen.read() );
2399    m_config_cmd_trdid_fifo.update(  config_cmd_fifo_get,
2400                                     config_cmd_fifo_put,
2401                                     r_config_cmd_trdid.read() );
2402    m_config_cmd_pktid_fifo.update(  config_cmd_fifo_get,
2403                                     config_cmd_fifo_put,
2404                                     r_config_cmd_pktid.read() );
2405    m_config_cmd_data_fifo.update(   config_cmd_fifo_get,
2406                                     config_cmd_fifo_put,
2407                                     r_config_cmd_wdata.read() );
2408    m_config_cmd_be_fifo.update(     config_cmd_fifo_get,
2409                                     config_cmd_fifo_put,
2410                                     r_config_cmd_be.read() );
2411    m_config_cmd_eop_fifo.update(    config_cmd_fifo_get,
2412                                     config_cmd_fifo_put,
2413                                     r_config_cmd_eop.read() );
2414
2415    //////////////////////////////////////////////////////////////////////////
2416    // CONFIG_RSP fifo update
2417    // writer : CONFIG_RSP FSM
2418    //////////////////////////////////////////////////////////////////////////
2419
2420    m_config_rsp_data_fifo.update(   config_rsp_fifo_get,
2421                                     config_rsp_fifo_put,
2422                                     config_rsp_fifo_rdata );
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 );
2438
2439    ////////////////////////////////////////////////////////////////
2440    // MISS_WTI_CMD fifo update
2441    // One writer : MISS_WTI switch
2442    ////////////////////////////////////////////////////////////////
2443
2444    m_miss_wti_cmd_addr_fifo.update(   miss_wti_cmd_fifo_get,
2445                                       miss_wti_cmd_fifo_put,
2446                                       miss_wti_cmd_fifo_address );
2447    m_miss_wti_cmd_cmd_fifo.update(    miss_wti_cmd_fifo_get,
2448                                       miss_wti_cmd_fifo_put,
2449                                       miss_wti_cmd_fifo_cmd );
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 );
2486
2487} // end transition()
2488
2489//////////////////////////////////////////////////////////////////////////
2490tmpl(void)::genMoore()
2491//////////////////////////////////////////////////////////////////////////
2492{
2493    /////////////////  p_vci_ini_ram  /////////////////////////////
2494
2495    // VCI initiator command on RAM network
2496    // directly the content of the dma_cmd FIFO
2497    p_vci_ini_ram.cmdval  = m_dma_cmd_addr_fifo.rok();
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();
2502    p_vci_ini_ram.wdata   = m_dma_cmd_data_fifo.read();
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();
2512
2513    // VCI initiator response on the RAM Network
2514    // depends on the DMA_RSP FSM state
2515    p_vci_ini_ram.rspack = m_dma_rsp_data_fifo.wok() and
2516                           (r_dma_rsp_fsm.read() == DMA_RSP_PUT_DMA);
2517
2518    /////////////////  p_vci_tgt_iox  /////////////////////////////
2519
2520    // VCI target response on IOX network is
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();
2526    p_vci_tgt_iox.rdata   = m_dma_rsp_data_fifo.read();
2527    p_vci_tgt_iox.rerror  = m_dma_rsp_rerror_fifo.read();
2528    p_vci_tgt_iox.reop    = m_dma_rsp_reop_fifo.read();
2529
2530    // VCI target command ack on IOX network
2531    // depends on the DMA_CMD FSM state
2532    switch ( r_dma_cmd_fsm.read() )
2533    {
2534        case DMA_CMD_IDLE:
2535             p_vci_tgt_iox.cmdack  = false;
2536             break;
2537        case DMA_CMD_DMA_REQ:
2538             p_vci_tgt_iox.cmdack  = m_dma_cmd_addr_fifo.wok();
2539             break;
2540        case DMA_CMD_WTI_IOX_REQ:
2541             p_vci_tgt_iox.cmdack  = not r_dma_cmd_to_miss_wti_cmd_req.read();
2542             break;
2543        case DMA_CMD_ERR_WTI_REQ:
2544             p_vci_tgt_iox.cmdack  = false;
2545             break;
2546        case DMA_CMD_ERR_WAIT_EOP:
2547             p_vci_tgt_iox.cmdack  = true;
2548             break;
2549        case DMA_CMD_ERR_RSP_REQ:
2550             p_vci_tgt_iox.cmdack  = false;
2551             break;
2552        case DMA_CMD_TLB_MISS_WAIT:
2553             p_vci_tgt_iox.cmdack  = false;
2554             break;
2555    }
2556
2557    //////////////////  p_vci_ini_iox  /////////////////////////////
2558
2559    // VCI initiator command on IOX network is
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();
2566    p_vci_ini_iox.wdata   = m_config_cmd_data_fifo.read();
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();
2575    p_vci_ini_iox.srcid   = m_iox_srcid;
2576
2577    // VCI initiator response on IOX Network
2578    // it depends on the CONFIG_RSP FSM state
2579    p_vci_ini_iox.rspack = m_config_rsp_data_fifo.wok() and
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();
2588    p_vci_tgt_int.rsrcid  = m_config_rsp_rsrcid_fifo.read();
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();
2594
2595    // VCI target command ack on INT network
2596    // it depends on the CONFIG_CMD FSM state
2597    switch ( r_config_cmd_fsm.read() )
2598    {
2599    case CONFIG_CMD_IDLE:
2600        p_vci_tgt_int.cmdack = true;
2601        break;
2602    case CONFIG_CMD_WAIT:
2603        p_vci_tgt_int.cmdack = false;
2604        break;
2605    case CONFIG_CMD_HI:
2606        p_vci_tgt_int.cmdack = true;
2607        break;
2608    case CONFIG_CMD_LO:
2609        p_vci_tgt_int.cmdack = true;
2610        break;
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;
2617    }
2618
2619    /////////////////  p_vci_ini_int  ////////////////////////////////
2620
2621    // VCI initiator command  on INT network
2622    // directly the content of the MISS_WTI_CMD FIFO
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();
2628    p_vci_ini_int.wdata   = m_miss_wti_cmd_data_fifo.read();
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();
2638
2639    // VCI initiator response on INT network
2640    // It depends on the MISS_WTI_RSP FSM state
2641
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    }
2654
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.