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

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

Cosmetic

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