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

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

debug...

File size: 87.9 KB
RevLine 
[434]1/* -*- c++ -*-
[240]2 * File : vci_io_bridge.cpp
3 * Copyright (c) UPMC, Lip6, SoC
[434]4 * Authors: Cassio Fraga, Alain Greiner
[240]5 *
6 * SOCLIB_LGPL_HEADER_BEGIN
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
[434]32
[240]33//////   debug services   ///////////////////////////////////////////////////////
34// All debug messages are conditionned by two variables:
35// - compile time : DEBUG_*** : defined below
36// - execution time : m_debug_***  : defined by constructor arguments
[434]37//    m_debug_activated = (m_debug_ok) and (m_cpt_cycle > m_debug_start_cycle)
[240]38/////////////////////////////////////////////////////////////////////////////////
39
40#define DEBUG_DMA_CMD           1
41#define DEBUG_DMA_RSP           1
[434]42#define DEBUG_TLB_MISS          1
[240]43#define DEBUG_CONFIG_CMD                1
44#define DEBUG_CONFIG_RSP                1
[434]45#define DEBUG_MISS_WTI                  1
[240]46
47namespace soclib { 
48namespace caba {
49
50namespace {
51
[434]52const char *dma_cmd_fsm_state_str[] = 
53    {
[240]54        "DMA_CMD_IDLE",
[434]55        "DMA_CMD_FIFO_PUT_CMD",
56        "DMA_CMD_FIFO_PUT_RSP",
57        "DMA_CMD_MISS_WAIT",
58        "DMA_CMD_WAIT_EOP",
[240]59    };
60
[434]61const char *dma_rsp_fsm_state_str[] = 
62    {
[240]63        "DMA_RSP_IDLE",
64        "DMA_RSP_FIFO_PUT",
65    };
66
[434]67const char *tlb_fsm_state_str[] = 
68    {
69        "TLB_IDLE",
70        "TLB_MISS",
71        "TLB_PTE1_GET",
72        "TLB_PTE1_SELECT",
73        "TLB_PTE1_UPDT",
74        "TLB_PTE2_GET",                                                 
75        "TLB_PTE2_SELECT",
76        "TLB_PTE2_UPDT",
77        "TLB_WAIT",
78        "TLB_RETURN",
79        "TLB_INVAL_CHECK",
[240]80    };
81
[434]82const char *config_cmd_fsm_state_str[] = 
83    {
[240]84        "CONFIG_CMD_IDLE",
[585]85        "CONFIG_CMD_NEXT",
86        "CONFIG_CMD_PUT",
87        "CONFIG_CMD_RSP",
[240]88    };
89
[434]90const char *config_rsp_fsm_state_str[] = 
91    {
[240]92        "CONFIG_RSP_IDLE",
[585]93        "CONFIG_RSP_PUT_LO", 
94        "CONFIG_RSP_PUT_HI", 
95        "CONFIG_RSP_PUT_UNC", 
[240]96    };
97
[549]98const char *miss_wti_cmd_state_str[] = 
99    { 
100        "MISS_WTI_CMD_IDLE",
[434]101        "MISS_WTI_CMD_WTI",
[549]102        "MISS_WTI_CMD_MISS",
103    };
104const char *miss_wti_rsp_state_str[] = 
105    { 
106        "MISS_WTI_RSP_IDLE",
[434]107        "MISS_WTI_RSP_WTI",
108        "MISS_WTI_RSP_MISS",
[240]109    };
110}
111
[434]112#define tmpl(...)  template<typename vci_param_int,typename vci_param_ext> __VA_ARGS__ VciIoBridge<vci_param_int,vci_param_ext>
[240]113
[434]114////////////////////////
[240]115tmpl(/**/)::VciIoBridge(
116    sc_module_name                                  name,
[434]117    const soclib::common::MappingTable  &mt_ext,
118    const soclib::common::MappingTable  &mt_int,
119    const soclib::common::MappingTable  &mt_iox,
120    const soclib::common::IntTab            &int_tgtid,     // INT network TGTID
121    const soclib::common::IntTab            &int_srcid,     // INT network SRCID
122    const soclib::common::IntTab            &iox_tgtid,     // IOX network TGTID
123    const bool                          has_irqs,
124    const size_t                        dcache_words,
125    const size_t                                        iotlb_ways,
126    const size_t                                        iotlb_sets,
127    const uint32_t                                      debug_start_cycle,
128    const bool                                      debug_ok)
[240]129    : soclib::caba::BaseModule(name),
130
[434]131      p_clk("p_clk"),
132      p_resetn("p_resetn"),
133      p_vci_ini_ram("p_vci_ini_ram"),
134      p_vci_tgt_iox("p_vci_tgt_iox"),
135      p_vci_ini_iox("p_vci_ini_iox"),
136      p_vci_tgt_int("p_vci_tgt_int"),
137      p_vci_ini_int("p_vci_ini_int"),
[240]138
[434]139      m_words( dcache_words ),
140      m_has_irqs( has_irqs ),
[240]141
[434]142      // INT & IOX Network
143      m_int_seglist( mt_int.getSegmentList( int_tgtid )),
144      m_int_srcid( mt_int.indexForId( int_srcid )), 
145      m_iox_seglist( mt_iox.getSegmentList( iox_tgtid )),
146
[240]147      m_iotlb_ways(iotlb_ways),
148      m_iotlb_sets(iotlb_sets),
149
150      m_debug_start_cycle(debug_start_cycle),
151      m_debug_ok(debug_ok),
152
[434]153      // addressable registers
[240]154      r_iommu_ptpr("r_iommu_ptpr"),
155      r_iommu_active("r_iommu_active"),
156      r_iommu_bvar("r_iommu_bvar"),
157      r_iommu_etr("r_iommu_etr"),
158      r_iommu_bad_id("r_iommu_bad_id"),
[434]159      r_iommu_wti_paddr("r_iommu_wti_paddr"),
160      r_iommu_peri_wti(alloc_elems<sc_signal<vci_addr_t> >("r_peri_wti_paddr", 32)),
[240]161
[434]162      // DMA_CMD FSM registers
[240]163      r_dma_cmd_fsm("r_dma_cmd_fsm"),
[434]164      r_dma_cmd_vaddr("r_dma_cmd_vaddr"),
165      r_dma_cmd_paddr("r_dma_cmd_paddr"),
[240]166
[434]167      //DMA_RSP FSM registers
168      r_dma_rsp_fsm("r_dma_rsp_fsm"),
[240]169
[434]170      // CONFIG_CMD FSM registers
171      r_config_cmd_fsm("r_config_cmd_fsm"),
172      r_config_cmd_rdata("r_config_cmd_rdata"),
173      r_config_cmd_error("r_config_cmd_error"),
174      r_config_cmd_inval_vaddr("r_config_cmd_inval_vaddr"),
[585]175      r_config_cmd_wdata("r_config_cmd_wdata"),
176      r_config_cmd_be("r_config_cmd_be"),
177      r_config_cmd_cmd("r_config_cmd_wdata"),
178      r_config_cmd_address("r_config_cmd_address"),
179      r_config_cmd_srcid("r_config_cmd_srcid"),
180      r_config_cmd_pktid("r_config_cmd_pktid"),
181      r_config_cmd_trdid("r_config_cmd_trdid"),
182      r_config_cmd_plen("r_config_cmd_plen"),
183      r_config_cmd_clen("r_config_cmd_clen"),
184      r_config_cmd_cons("r_config_cmd_cons"),
185      r_config_cmd_contig("r_config_cmd_contig"),
186      r_config_cmd_cfixed("r_config_cmd_cfixed"),
187      r_config_cmd_wrap("r_config_cmd_wrap"),
188      r_config_cmd_eop("r_config_cmd_eop"),
[240]189
[434]190      // CONFIG_RSP FSM registers 
191      r_config_rsp_fsm("r_config_rsp_fsm"),
192
193      // TLB FSM registers
194      r_tlb_fsm("r_tlb_fsm"),
[240]195      r_waiting_transaction("r_waiting_transaction"),
196      r_tlb_miss_type("r_tlb_miss_type"),
[434]197      r_tlb_miss_error("r_tlb_miss_error"),
198      r_tlb_paddr("r_tlb_paddr"),               
199      r_tlb_pte_flags("r_tlb_pte_flags"),
200      r_tlb_pte_ppn("r_tlb_pte_ppn"),
201      r_tlb_way("r_tlb_way"),
202      r_tlb_set("r_tlb_set"),   
203      r_tlb_buf_valid("r_tlb_buf_valid"),
204      r_tlb_buf_tag("r_tlb_buf_tag"),
205      r_tlb_buf_vaddr("r_tlb_buf_vaddr"),
206      r_tlb_buf_big_page("r_tlb_buf_big_page"),
[240]207
[434]208      // MISS_WTI_CMD FSM registers
209      r_miss_wti_cmd_fsm("r_miss_wti_cmd_fsm"), 
210      r_miss_wti_cmd_index("r_miss_wti_cmd_index"),
[240]211
[434]212      // MISS_WTI_CMD FSM registers
213      r_miss_wti_rsp_fsm("r_miss_wti_rsp_fsm"), 
214      r_miss_wti_rsp_error("r_miss_wti_rsp_error"),
215
216      // allocator for CONFIG_RSP & DMA_RSP fifos
217      r_alloc_fifo_config_rsp_local("r_alloc_fifo_config_rsp_local"), 
218      r_alloc_fifo_dma_rsp_local("r_alloc_fifo_dma_rsp_local"), 
219
220      // IRQs registers
221      r_irq_pending(alloc_elems<sc_signal<bool> >("r_irq_pending", 32)),
222      r_irq_request(alloc_elems<sc_signal<bool> >("r_irq_request", 32)),
[240]223     
[434]224      // TLB for IOMMU
225      r_iotlb("iotlb", 0, iotlb_ways, iotlb_sets, vci_param_int::N),
226     
227      // Inter-FSM communications
[240]228      r_dma_tlb_req("r_dma_tlb_req"),
229      r_config_tlb_req("r_config_tlb_req"),
[434]230      r_tlb_miss_req("r_tlb_miss_req"),
[240]231     
[434]232      // DMA_CMD FIFOs
233      m_dma_cmd_addr_fifo("m_dma_cmd_addr_fifo",2),
234      m_dma_cmd_srcid_fifo("m_dma_cmd_srcid_fifo",2), 
235      m_dma_cmd_trdid_fifo("m_dma_cmd_trdid_fifo",2), 
236      m_dma_cmd_pktid_fifo("m_dma_cmd_pktid_fifo",2), 
237      m_dma_cmd_be_fifo("m_dma_cmd_be_fifo",2), 
238      m_dma_cmd_cmd_fifo("m_dma_cmd_cmd_fifo",2), 
239      m_dma_cmd_contig_fifo("m_dma_cmd_contig_fifo",2), 
240      m_dma_cmd_data_fifo("m_dma_cmd_data_fifo",2), 
241      m_dma_cmd_eop_fifo("m_dma_cmd_eop_fifo",2),
242      m_dma_cmd_cons_fifo("m_dma_cmd_cons_fifo",2), 
243      m_dma_cmd_plen_fifo("m_dma_cmd_plen_fifo",2), 
244      m_dma_cmd_wrap_fifo("m_dma_cmd_wrap_fifo",2), 
245      m_dma_cmd_cfixed_fifo("m_dma_cmd_cfixed_fifo",2),
246      m_dma_cmd_clen_fifo("m_dma_cmd_clen_fifo",2), 
[240]247
[434]248      // DMA_RSP FIFOs
249      m_dma_rsp_data_fifo("m_dma_rsp_data_fifo",2),
250      m_dma_rsp_rsrcid_fifo("m_dma_rsp_rsrcid_fifo",2),
251      m_dma_rsp_rtrdid_fifo("m_dma_rsp_rtrdid_fifo",2),
252      m_dma_rsp_rpktid_fifo("m_dma_rsp_rpktid_fifo",2),
253      m_dma_rsp_reop_fifo("m_dma_rsp_reop_fifo",2),
254      m_dma_rsp_rerror_fifo("m_dma_rsp_rerror_fifo",2),
255 
256      // CONFIG_CMD FIFOs
257      m_config_cmd_addr_fifo("m_config_cmd_addr_fifo",2),
258      m_config_cmd_srcid_fifo("m_config_cmd_srcid_fifo",2),
259      m_config_cmd_trdid_fifo("m_config_cmd_trdid_fifo",2),
260      m_config_cmd_pktid_fifo("m_config_cmd_pktid_fifo",2),
261      m_config_cmd_be_fifo("m_config_cmd_be_fifo",2),
262      m_config_cmd_cmd_fifo("m_config_cmd_cmd_fifo",2),
263      m_config_cmd_contig_fifo("m_config_cmd_contig_fifo",2),
264      m_config_cmd_data_fifo("m_config_cmd_data_fifo",2),
265      m_config_cmd_eop_fifo("m_config_cmd_eop_fifo",2),
266      m_config_cmd_cons_fifo("m_config_cmd_cons_fifo",2),
267      m_config_cmd_plen_fifo("m_config_cmd_plen_fifo",2),
268      m_config_cmd_wrap_fifo("m_config_cmd_wrap_fifo",2),
269      m_config_cmd_cfixed_fifo("m_config_cmd_cfixed_fifo",2),
270      m_config_cmd_clen_fifo("m_config_cmd_clen_fifo",2),
271
272      // CONFIG_RSP FIFOs
273      m_config_rsp_data_fifo("m_config_rsp_data_fifo",2),     
274      m_config_rsp_rsrcid_fifo("m_config_rsp_rsrcid_fifo",2),
275      m_config_rsp_rtrdid_fifo("m_config_rsp_rtrdid_fifo",2),
276      m_config_rsp_rpktid_fifo("m_config_rsp_rpktid_fifo",2),
277      m_config_rsp_reop_fifo("m_config_rsp_reop_fifo",2),
278      m_config_rsp_rerror_fifo("m_config_rsp_rerror_fifo",2)
[240]279{
[434]280    std::cout << "  - Building VciIoBridge : " << name << std::endl;
281
282    // checking segments on INT network
283    assert ( ( not m_int_seglist.empty() ) and
284    "VCI_IO_BRIDGE ERROR : no segment allocated on INT network");
285
286    std::list<soclib::common::Segment>::iterator int_seg;
287    for ( int_seg = m_int_seglist.begin() ; int_seg != m_int_seglist.end() ; int_seg++ )
288    {
289        std::cout << "    => segment " << int_seg->name()
290                  << " / base = " << std::hex << int_seg->baseAddress()
[549]291                  << " / size = " << int_seg->size() 
292                  << " / special = " << int_seg->special() << std::endl; 
[434]293    }
294
295    // checking segments on IOX network
296    assert ( ( not m_iox_seglist.empty() ) and
297    "VCI_IO_BRIDGE ERROR : no segment allocated on IOX network");
298
299    std::list<soclib::common::Segment>::iterator iox_seg;
300    for ( iox_seg = m_iox_seglist.begin() ; iox_seg != m_iox_seglist.end() ; iox_seg++ )
301    {
302        std::cout << "    => segment " << iox_seg->name()
303                  << " / base = " << std::hex << iox_seg->baseAddress()
304                  << " / size = " << iox_seg->size() << std::endl; 
305    }
306
307    assert( (vci_param_int::N == vci_param_ext::N) and
308    "VCI_IO_BRIDGE ERROR: VCI ADDRESS widths must be equal on the 3 networks");
309
310    assert( (vci_param_int::N <=  64) and
311    "VCI_IO_BRIDGE ERROR: VCI ADDRESS width cannot be bigger than 64 bits");
312
[585]313    assert( (vci_param_int::B == 4) and
314    "VCI_IO_BRIDGE ERROR: VCI DATA width must be 32 bits on internal network");   
[434]315
[585]316    assert( (vci_param_ext::B == 8) and
317    "VCI_IO_BRIDGE ERROR: VCI DATA width must be 64 bits on external network");   
[434]318
319    assert( (vci_param_int::S == vci_param_ext::S) and
320            "VCI_IO_BRIDGE ERROR: SRCID widths must be equal on the 3 networks");
321
322    // contruct 32 IRQ ports if required
323    if ( has_irqs )
324    {
325        for ( size_t n=0 ; n<32 ; n++ ) p_irq[n] = new sc_core::sc_in<bool>;
326    }
[240]327   
[434]328    // Cache line buffer
329    r_tlb_buf_data = new uint32_t[dcache_words];
330
[240]331    SC_METHOD(transition);
332    dont_initialize();
333    sensitive << p_clk.pos();
334 
335    SC_METHOD(genMoore);
336    dont_initialize();
337    sensitive << p_clk.neg();
338
339 }
340
341/////////////////////////////////////
342tmpl(/**/)::~VciIoBridge()
343/////////////////////////////////////
344{
[434]345    delete [] r_iommu_peri_wti;
346    delete [] r_tlb_buf_data;
347    soclib::common::dealloc_elems(p_irq, 32);
348    soclib::common::dealloc_elems(r_irq_request, 32);
349    soclib::common::dealloc_elems(r_irq_pending, 32);
[240]350}
351
352////////////////////////////////////
353tmpl(void)::print_trace(size_t mode)
354////////////////////////////////////
355{
[549]356    // b0 : IOTLB trace
[240]357
358    std::cout << std::dec << "IO_BRIDGE " << name() << std::endl;
359
[434]360    std::cout << "  "  << dma_cmd_fsm_state_str[r_dma_cmd_fsm.read()]
[240]361              << " | " << dma_rsp_fsm_state_str[r_dma_rsp_fsm.read()]
[434]362              << " | " << tlb_fsm_state_str[r_tlb_fsm.read()]
[240]363              << " | " << config_cmd_fsm_state_str[r_config_cmd_fsm.read()]
364              << " | " << config_rsp_fsm_state_str[r_config_rsp_fsm.read()]
[549]365              << " | " << miss_wti_cmd_state_str[r_miss_wti_cmd_fsm.read()]
366              << " | " << miss_wti_rsp_state_str[r_miss_wti_rsp_fsm.read()]
[434]367              << std::endl;
[240]368
369    if(mode & 0x01)
370    {
371        std::cout << "  IOTLB" << std::endl;
372        r_iotlb.printTrace();
373    }
374}
375
376////////////////////////
377tmpl(void)::print_stats()
378////////////////////////
379{
380    std::cout << name() << std::endl
381        << "- IOTLB MISS RATE      = " << (float)m_cpt_iotlb_miss/m_cpt_iotlb_read << std::endl
382        << "- IOTLB MISS COST         = " << (float)m_cost_iotlb_miss/m_cpt_iotlb_miss << std::endl
383        << "- IOTLB MISS TRANSACTION COST  = " << (float)m_cost_iotlbmiss_transaction/m_cpt_iotlbmiss_transaction << std::endl
384        << "- IOTLB MISS TRANSACTION RATE (OVER ALL MISSES)  = " << (float)m_cpt_iotlbmiss_transaction/m_cpt_iotlb_miss << std::endl;
385}
386
387////////////////////////
388tmpl(void)::clear_stats()
389////////////////////////
390{
391    m_cpt_iotlb_read                = 0;             
392    m_cpt_iotlb_miss                = 0;             
393    m_cost_iotlb_miss               = 0;
394    m_cpt_iotlbmiss_transaction     = 0;   
395    m_cost_iotlbmiss_transaction    = 0;   
396}
397
398/////////////////////////
399tmpl(void)::transition()
400/////////////////////////
401{
402    if ( not p_resetn.read() ) 
403    {
[434]404        r_dma_cmd_fsm      = DMA_CMD_IDLE;
405        r_dma_rsp_fsm      = DMA_RSP_IDLE;
406        r_tlb_fsm              = TLB_IDLE;
407        r_config_cmd_fsm   = CONFIG_CMD_IDLE;
408        r_config_rsp_fsm   = CONFIG_RSP_IDLE;
409        r_miss_wti_cmd_fsm = MISS_WTI_CMD_IDLE;
410        r_miss_wti_rsp_fsm = MISS_WTI_RSP_IDLE;
[240]411
[434]412        r_alloc_fifo_config_rsp_local = true;
413        r_alloc_fifo_dma_rsp_local    = true;
[240]414
[434]415        r_tlb_buf_valid    = false; 
416                r_iommu_active     = false;
417                r_iommu_wti_enable = false;
[240]418       
419        // initializing FIFOs
420        m_dma_cmd_addr_fifo.init();
421        m_dma_cmd_srcid_fifo.init();
422        m_dma_cmd_trdid_fifo.init();
423        m_dma_cmd_pktid_fifo.init();
424        m_dma_cmd_be_fifo.init();
425        m_dma_cmd_cmd_fifo.init();
426        m_dma_cmd_contig_fifo.init();
427        m_dma_cmd_data_fifo.init();
428        m_dma_cmd_eop_fifo.init();
429        m_dma_cmd_cons_fifo.init();
430        m_dma_cmd_plen_fifo.init();
431        m_dma_cmd_wrap_fifo.init();
432        m_dma_cmd_cfixed_fifo.init();
433        m_dma_cmd_clen_fifo.init();
434       
435        m_dma_rsp_rsrcid_fifo.init();
436        m_dma_rsp_rtrdid_fifo.init();
437        m_dma_rsp_rpktid_fifo.init();
438        m_dma_rsp_data_fifo.init();
439        m_dma_rsp_rerror_fifo.init();
440        m_dma_rsp_reop_fifo.init();
441       
442        m_config_cmd_addr_fifo.init();
443        m_config_cmd_srcid_fifo.init();
444        m_config_cmd_trdid_fifo.init();
445        m_config_cmd_pktid_fifo.init();
446        m_config_cmd_be_fifo.init();
447        m_config_cmd_cmd_fifo.init();
448        m_config_cmd_contig_fifo.init();
449        m_config_cmd_data_fifo.init();
450        m_config_cmd_eop_fifo.init();
451        m_config_cmd_cons_fifo.init();
452        m_config_cmd_plen_fifo.init();
453        m_config_cmd_wrap_fifo.init();
454        m_config_cmd_cfixed_fifo.init();
455        m_config_cmd_clen_fifo.init();
456       
457        m_config_rsp_rsrcid_fifo.init();
458        m_config_rsp_rtrdid_fifo.init();
459        m_config_rsp_rpktid_fifo.init();
460        m_config_rsp_data_fifo.init();
461        m_config_rsp_rerror_fifo.init();
462        m_config_rsp_reop_fifo.init();
463       
[434]464        // SET/RESET Communication flip-flops
465        r_dma_tlb_req                   = false;
466        r_config_tlb_req                    = false;
467        r_tlb_miss_req              = false;
[240]468
[434]469        // Debug variable
470                m_debug_activated               = false;
[240]471       
[434]472        for ( size_t n=0 ; n<32 ; n++ )
473        {
474            r_irq_pending[n]        = false;
475            r_irq_request[n]        = false;
476        }
[240]477         
478            // activity counters
[434]479            m_cpt_total_cycles            = 0;
480        m_cpt_iotlb_read              = 0;             
481        m_cpt_iotlb_miss              = 0;             
482        m_cpt_iotlbmiss_transaction   = 0;   
483        m_cost_iotlbmiss_transaction  = 0;   
[240]484       
[434]485        m_cpt_trt_dma_full            = 0;
486        m_cpt_trt_dma_full_cost       = 0;
487        m_cpt_trt_config_full         = 0;
488        m_cpt_trt_config_full_cost    = 0;
[240]489
490        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_dma_cmd            [i]   = 0;
491        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_dma_rsp            [i]   = 0;
[434]492        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_tlb                [i]   = 0;
[240]493        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_config_cmd         [i]   = 0;
494        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_config_rsp         [i]   = 0;
[434]495        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_miss_wti_cmd       [i]   = 0;
496        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_miss_wti_rsp       [i]   = 0;
497
[240]498        return;
499    }
500
[434]501    // default values for FIFOs
502    bool        dma_cmd_fifo_put      = false;
503    bool        dma_cmd_fifo_get      = false;
504
505    bool        dma_rsp_fifo_put      = false; 
506    bool        dma_rsp_fifo_get      = false; 
[240]507   
[434]508    bool        config_cmd_fifo_put   = false;
509    bool        config_cmd_fifo_get   = false;
[240]510
[434]511    bool        config_rsp_fifo_put   = false;
512    bool        config_rsp_fifo_get   = false;
513
[240]514#ifdef INSTRUMENTATION
515    m_cpt_fsm_dma_cmd           [r_dma_cmd_fsm.read()] ++;
516    m_cpt_fsm_dma_rsp           [r_dma_rsp_fsm.read() ] ++;
[434]517    m_cpt_fsm_tlb                   [r_tlb_fsm.read() ] ++;
[240]518    m_cpt_fsm_config_cmd            [r_config_cmd_fsm.read() ] ++;
519    m_cpt_fsm_config_rsp            [r_config_rsp_fsm.read() ] ++;
[434]520    m_cpt_fsm_miss_wti_cmd      [r_miss_wti_cmd_fsm.read() ] ++;
521    m_cpt_fsm_miss_wti_rsp      [r_miss_wti_rsp_fsm.read() ] ++;
[240]522#endif
523
524    m_cpt_total_cycles++;
525
[434]526    m_debug_activated  = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;
[240]527
[434]528    //////////////////////////////////////////////////////////////////////////////
529    // The DMA_CMD_FSM handles DMA transactions requested by peripherals
530    // It makes the address translation if IOMMU is activated.
[240]531    ///////////////////////////////////////////////////////////////////////////////
532
533    switch( r_dma_cmd_fsm.read() ) 
534    {
[434]535    //////////////////
536    case DMA_CMD_IDLE:  // waiting DMA VCI transaction
[240]537    {
[434]538        if ( p_vci_tgt_iox.cmdval.read() ) // compute physical address
[240]539        { 
[434]540            if ( not r_iommu_active.read() )    // tlb not activated
[240]541            {
[434]542#if DEBUG_DMA_CMD
543if( m_debug_activated )
[585]544std::cout << "  <IOB DMA_CMD_IDLE> @@@ dma command" << std::endl
545          << "  address = " << std::hex << p_vci_tgt_iox.address.read()
546          << " / srcid = " << p_vci_tgt_iox.srcid.read()
547          << " / trdid = " << p_vci_tgt_iox.trdid.read()
548          << " / wdata = " << std::hex << p_vci_tgt_iox.wdata.read()
549          << " / be = " << p_vci_tgt_iox.be.read()
550          << " / plen = " << std::dec << p_vci_tgt_iox.plen.read()
551          << " / eop = " << p_vci_tgt_iox.eop.read() << std::endl;
552
[434]553#endif
554                // put DMA transaction into DMA_CMD fifo
555                r_dma_cmd_paddr = p_vci_tgt_iox.address.read();
556                r_dma_cmd_fsm   = DMA_CMD_FIFO_PUT_CMD;
[240]557            }
[434]558            else if (r_tlb_fsm.read() == TLB_IDLE ||
559                     r_tlb_fsm.read() == TLB_WAIT )       // tlb access possible
[240]560            {
[434]561                vci_addr_t      iotlb_paddr;
[240]562                pte_info_t  iotlb_flags; 
563                size_t      iotlb_way; 
564                size_t      iotlb_set;
[434]565                vci_addr_t  iotlb_nline;
566                bool            iotlb_hit; 
[240]567
568#ifdef INSTRUMENTATION
569m_cpt_iotlb_read++;
570#endif
[434]571                iotlb_hit = r_iotlb.translate(p_vci_tgt_iox.address.read(),
572                                              &iotlb_paddr,
573                                              &iotlb_flags,
574                                              &iotlb_nline,  // unused
575                                              &iotlb_way,        // unused
576                                              &iotlb_set );  // unused
[240]577           
[434]578                if ( iotlb_hit )                                     // tlb hit
[240]579                { 
[434]580                    if ( not iotlb_flags.w and    // access right violation
581                        (p_vci_tgt_iox.cmd.read() == vci_param_ext::CMD_WRITE) ) 
[240]582                    {
[434]583                        // put DMA response error into DMA_RSP fifo
584                        r_iommu_etr      = MMU_WRITE_ACCES_VIOLATION; 
585                        r_iommu_bvar     = p_vci_tgt_iox.address.read();
586                        r_iommu_bad_id   = p_vci_tgt_iox.srcid.read();
587                        r_dma_cmd_fsm    = DMA_CMD_FIFO_PUT_RSP;
[240]588#if DEBUG_DMA_CMD
[434]589if( m_debug_activated )
590std::cout << "  <IOB DMA_CMD_IDLE> TLB HIT but writable violation" << std::endl;
[240]591#endif
592                    }
[434]593                    else                         // no access rights violation
594                    {
595#if DEBUG_DMA_CMD
596if( m_debug_activated )
597std::cout << "  <IOB DMA_CMD_IDLE> TLB HIT" << std::endl;
598#endif
599                    // put DMA transaction into DMA_CMD fifo
600                    r_dma_cmd_paddr   = iotlb_paddr;                   
601                    r_dma_cmd_fsm     = DMA_CMD_FIFO_PUT_CMD;
602                    }
[240]603                }
[434]604                else                                             // TLB miss
[240]605                {
606
607#ifdef INSTRUMENTATION
608m_cpt_iotlb_miss++;
609#endif
[434]610                        // register virtual address, and send request to TLB FSM
611                                r_dma_cmd_vaddr = p_vci_tgt_iox.address.read();
[240]612                        r_dma_tlb_req   = true;
[434]613                        r_dma_cmd_fsm   = DMA_CMD_MISS_WAIT;
[240]614#if DEBUG_DMA_CMD
[434]615if( m_debug_activated )
616std::cout << "  <IOB DMA_CMD_IDLE> TLB MISS" << std::endl;
[240]617#endif
618                } // end !hit
619            } // end if tlb_activated
620        } // end if cmdval
621        break;
622    }
[434]623    //////////////////////////
624    case DMA_CMD_FIFO_PUT_CMD:    // put a DMA transaction in DMA_CMD fifo       
625                                  // if contig, VCI address must be incremented
[240]626    {
[434]627        if ( p_vci_tgt_iox.cmdval && m_dma_cmd_addr_fifo.wok() ) 
[240]628        {
[434]629            dma_cmd_fifo_put = true;
630           
631            if ( p_vci_tgt_iox.contig.read() ) r_dma_cmd_paddr = r_dma_cmd_paddr.read() + 
632                                                          vci_param_ext::B;
[240]633
[434]634            if ( p_vci_tgt_iox.eop.read() )    r_dma_cmd_fsm   = DMA_CMD_IDLE;
635           
[240]636#if DEBUG_DMA_CMD
[434]637if( m_debug_activated ) 
638std::cout << "  <IOB DMA_CMD_FIFO_PUT_CMD> Push into DMA_CMD fifo:" 
639          << " address = " << std::hex << r_dma_cmd_paddr.read()
640          << " srcid = " << p_vci_tgt_iox.srcid.read()
641          << " trdid = " << p_vci_tgt_iox.trdid.read()
642          << " wdata = " << p_vci_tgt_iox.wdata.read()
643          << " be = " << p_vci_tgt_iox.be.read()
644          << " contig = " << p_vci_tgt_iox.contig.read()
645          << " eop = " << std::dec << p_vci_tgt_iox.eop.read() 
646          << " plen = " << std::dec << p_vci_tgt_iox.plen.read() << std::endl;
[240]647#endif
648        }
649        break;
650    }
[434]651    //////////////////////
652    case DMA_CMD_WAIT_EOP:       // An error has been detected on the VCI DMA command
653                             // consume the VCI packet before sending the error response
[240]654    {
[434]655        if ( p_vci_tgt_iox.eop.read() )    r_dma_cmd_fsm   = DMA_CMD_FIFO_PUT_RSP;
[240]656        break;
657    }
[434]658    //////////////////////////
659    case DMA_CMD_FIFO_PUT_RSP:   // try to put a response error in DMA_RSP fifo
660                                 // The FIFO is shared with DMA_RSP FSM
661                                 // and we must we wait for allocation...
[240]662    {
[434]663        if ( r_alloc_fifo_dma_rsp_local.read() ) 
[240]664        {
[434]665            dma_rsp_fifo_put = true;
666
667            if( m_dma_rsp_data_fifo.wok() )
[240]668            {
669
670#if DEBUG_DMA_CMD
[434]671if( m_debug_activated ) 
672std::cout << "  <IOB DMA_CMD_FIFO_PUT_RSP> Put a response error to a DMA transaction." 
673          << std::endl;
[240]674#endif
[434]675                r_dma_cmd_fsm = DMA_CMD_IDLE;
676            }
[240]677        }
678        break;
679    }
[434]680    ///////////////////////
681    case DMA_CMD_MISS_WAIT:  // waiting completion of a TLB miss
682                             // we must test a possible page fault error...   
[240]683    {
[434]684        if ( not r_dma_tlb_req.read() ) // TLB miss completed
[240]685        {
[434]686            if ( r_tlb_miss_error.read() )   // Error reported by TLB FSM
[240]687            {
[434]688                r_iommu_etr     = MMU_READ_PT2_UNMAPPED; 
689                r_iommu_bvar    = r_dma_cmd_vaddr.read();
690                r_iommu_bad_id  = p_vci_tgt_iox.srcid.read();
691                r_dma_cmd_fsm   = DMA_CMD_FIFO_PUT_RSP;
[240]692            }
[434]693            else                            // No error
694            {
695                r_dma_cmd_fsm   = DMA_CMD_IDLE;
696            }
[240]697        }
698        break;
699    }
[434]700    } // end switch DMA_CMD FSM
[240]701
702    //////////////////////////////////////////////////////////////////////////////
[434]703    // The DMA_RSP_FSM handles the RAM responses to peripherals DMA transactions.
704    //////////////////////////////////////////////////////////////////////////////
705
[240]706    switch( r_dma_rsp_fsm.read() ) 
707    {
[434]708    //////////////////
709    case DMA_RSP_IDLE:  // waiting a response from RAM betwork
[240]710    {           
[434]711        if ( p_vci_ini_ram.rspval.read() ) 
[240]712                {
[434]713                        r_dma_rsp_fsm = DMA_RSP_FIFO_PUT;
[240]714                }
715                break;
716    }
[434]717    //////////////////////
[240]718    case DMA_RSP_FIFO_PUT:
719    {
[434]720        if(p_vci_ini_ram.rspval.read() and not r_alloc_fifo_dma_rsp_local.read() )
[240]721        {
722            dma_rsp_fifo_put = true;
723
[434]724            if(p_vci_ini_ram.reop.read())   r_dma_rsp_fsm = DMA_RSP_IDLE;       
[240]725
726#if DEBUG_DMA_RSP
[434]727if( m_debug_activated ) 
728std::cout << "  <IOB DMA_RSP_FIFO_PUT> Push response into DMA_RSP fifo:" 
729          << " / rsrcid = " << std::hex << p_vci_ini_ram.rsrcid.read()
730          << " / rtrdid = " << p_vci_ini_ram.rtrdid.read()
731          << " / rdata = " << std::hex << p_vci_ini_ram.rdata.read()
732          << " / rerror = " << p_vci_ini_ram.rerror.read()
733          << " / reop = " << p_vci_ini_ram.reop.read() << std::endl;
[240]734#endif
735        }
736        break;
737    }
738    } // end switch DMA_RSP_FSM
739
[434]740    //////////////////////////////////////////////////////////////////////////////////
741    // The TLB FSM handles TLB miss request (from DMA_CMD FSM),
742    // and the PTE inval request (from CONFIG_CMD FSM).
743    // PTE inval request have highest priority. In case of TLB miss,
744    // this fsm searchs the requested PTE on the prefetch buffer.
745    // In case of buffer miss,  it request the MISS_WTI FSM to access the memory.
[240]746    // It bypass the first level page table access if possible.
[434]747    // It reset the r_dma_tlb_req flip-flop to signal TLB miss completion.
748    // An unexpected, but possible page fault is signaled in r_tlb_miss_error flip_flop.
[240]749    ////////////////////////////////////////////////////////////////////////////////////
[434]750
751    switch (r_tlb_fsm.read())
[240]752    {
[434]753    //////////////
754    case TLB_IDLE:   // In case of TLB miss request, chek the prefetch buffer first
755                     // PTE inval request are handled as unmaskable interrupts
[240]756    {
[434]757        if ( r_config_tlb_req ) // Request from CONFIG FSM for a PTE invalidation
[240]758        {
[434]759            r_config_tlb_req      = false;
[240]760            r_waiting_transaction = false;
[434]761            r_tlb_fsm = TLB_INVAL_CHECK;
[240]762        }
[434]763
764        else if ( r_dma_tlb_req.read() )   // request from DMA_CMD for a TLB Miss
[240]765        {
[434]766            // Checking prefetch buffer
767            if( not r_tlb_buf_big_page )     // small page => PTE2
[240]768            {
[434]769                if( r_tlb_buf_valid &&         // Hit on prefetch buffer
770                    (r_tlb_buf_vaddr.read() == 
771                    (r_dma_cmd_vaddr.read()& ~PTE2_LINE_OFFSET & ~K_PAGE_OFFSET_MASK)))
772                {
773                    size_t   pte_offset = (r_dma_cmd_vaddr.read()& PTE2_LINE_OFFSET)>>12; 
774                    uint32_t pte_flags  = r_tlb_buf_data[2*pte_offset];
775                    uint32_t pte_ppn    = r_tlb_buf_data[2*pte_offset+1]; 
[240]776               
[434]777                    // Bit valid checking
778                    if ( not ( pte_flags & PTE_V_MASK) )        // unmapped
779                    {
780                        std::cout << "VCI_IO_BRIDGE ERROR : " << name() 
781                                  << " Page Table entry unmapped" << std::endl;
[240]782                       
[434]783                        r_tlb_miss_error = true;
784                        r_dma_tlb_req    = false;
785#if DEBUG_TLB_MISS
786if ( m_debug_activated )
787std::cout << "  <IOB TLB_IDLE> PTE2 Unmapped" << std::hex
788          << " / paddr = " << r_tlb_paddr.read()
789          << " / PTE_FLAGS = " << pte_flags
790          << " / PTE_PPN = " << pte_ppn << std::endl;
[240]791#endif
[434]792                        break; 
793                    }
[240]794
[434]795                    // valid PTE2 : we must update the TLB
796                    r_tlb_pte_flags = pte_flags; 
797                    r_tlb_pte_ppn   = pte_ppn;
798                    r_tlb_fsm       = TLB_PTE2_SELECT;
799#if DEBUG_TLB_MISS
800if ( m_debug_activated )
801std::cout << "  <IOB TLB_IDLE> Hit on prefetch buffer: PTE2" << std::hex
802          << " / PTE_FLAGS = " << pte_flags
803          << " / PTE_PPN = " << pte_ppn << std::endl;
[240]804#endif
[434]805                    break;   
806                }
[240]807            }
[434]808            else                             // big page => PTE1
[240]809            {
[434]810                if( r_tlb_buf_valid &&         // Hit on prefetch buffer
811                    (r_tlb_buf_vaddr.read() == 
812                    (r_dma_cmd_vaddr.read()& ~PTE1_LINE_OFFSET & ~M_PAGE_OFFSET_MASK ))) 
813                {
814                    size_t   pte_offset = (r_dma_cmd_vaddr.read()& PTE1_LINE_OFFSET)>>21; 
815                    uint32_t pte_flags  = r_tlb_buf_data[pte_offset];
[240]816                           
[434]817                    // Bit valid checking
818                    if ( not ( pte_flags & PTE_V_MASK) )        // unmapped
819                    {
820                        std::cout << "VCI_IO_BRIDGE ERROR : " << name() 
821                                  << " Page Table entry unmapped" << std::endl;
[240]822                       
[434]823                        r_tlb_miss_error = true;
824                        r_dma_tlb_req    = false;
825#if DEBUG_TLB_MISS
826if ( m_debug_activated )
827std::cout << "  <IOB TLB_IDLE> PTE1 Unmapped" << std::hex
828          << " / paddr = " << r_tlb_paddr.read()
829          << " / PTE = " << pte_flags << std::endl;
[240]830#endif
[434]831                        break; 
832                    }
[240]833
[434]834                    // valid PTE1 : we must update the TLB
835                    r_tlb_pte_flags = pte_flags;
836                    r_tlb_fsm       = TLB_PTE1_SELECT;
837#if DEBUG_TLB_MISS
838if ( m_debug_activated )
839std::cout << "  <IOB TLB_PTE1_GET> Hit on prefetch buffer: PTE1" << std::hex
840          << " / paddr = " << r_tlb_paddr.read()
841          << std::hex << " / PTE1 = " << pte_flags << std::endl;
[240]842#endif
[434]843                    break;
[240]844                }
845            }
846       
[434]847            // prefetch buffer miss
848            r_tlb_fsm = TLB_MISS; 
[240]849
[434]850#if DEBUG_TLB_MISS
851if ( m_debug_activated )
852std::cout << "  <IOB TLB_IDLE> Miss on prefetch buffer"
853          << std::hex << " / vaddr = " << r_dma_cmd_vaddr.read() << std::endl;
[240]854#endif
855        }
856        break;
857    }
[434]858    //////////////
859    case TLB_MISS: // handling tlb miss
[240]860    {
[434]861        uint32_t        ptba = 0; 
[240]862        bool            bypass;
[434]863        vci_addr_t      pte_paddr;
[240]864
[434]865#ifdef INSTRUMENTATION
866m_cpt_iotlbmiss_transaction++;
867#endif
[240]868        // evaluate bypass in order to skip first level page table access
[434]869        bypass = r_iotlb.get_bypass(r_dma_cmd_vaddr.read(), &ptba);
[240]870       
[434]871        // Request MISS_WTI_FSM a transaction on INT Network
[240]872        if ( not bypass )     // Read PTE1/PTD1 in XRAM
873        {
[434]874
875#if DEBUG_TLB_MISS
876if ( m_debug_activated )
877std::cout << "  <IOB TLB_MISS> Read PTE1/PTD1 in memory" << std::endl;
878#endif
879            pte_paddr = (vci_addr_t)((r_iommu_ptpr.read()) << (INDEX1_NBITS+2)) |
880                        (vci_addr_t)((r_dma_cmd_vaddr.read() >> PAGE_M_NBITS) << 2);
881            r_tlb_paddr = pte_paddr;
[240]882           
[434]883            r_tlb_miss_req     = true;
884            r_tlb_miss_type    = PTE1_MISS;
885            r_tlb_fsm          = TLB_WAIT;
[240]886        }
887        else                  // Read PTE2 in XRAM
888        {
[434]889
890#if DEBUG_TLB_MISS
891if ( m_debug_activated )
892std::cout << "  <IOB TLB_MISS> Read PTE2 in memory" << std::endl;
893#endif
[240]894            //&PTE2 = PTBA + IX2 * 8
[434]895            pte_paddr = (vci_addr_t)ptba << PAGE_K_NBITS |
896                        (vci_addr_t)(r_dma_cmd_vaddr.read()&PTD_ID2_MASK)>>(PAGE_K_NBITS-3);
[240]897           
[434]898            r_tlb_paddr = pte_paddr;
[240]899           
[434]900            r_tlb_miss_req     = true;
901            r_tlb_miss_type    = PTE2_MISS;
902            r_tlb_fsm          = TLB_WAIT;
[240]903        }
904
905        break;
906    }
[434]907    ////////////////// 
908    case TLB_PTE1_GET:  // Try to read a PT1 entry in the miss buffer
[240]909    {
910       
911        uint32_t  entry;
912       
[434]913        vci_addr_t line_number  = (vci_addr_t)((r_tlb_paddr.read())&(CACHE_LINE_MASK));
914        size_t word_position = (size_t)( ((r_tlb_paddr.read())&(~CACHE_LINE_MASK))>>2 );
[240]915
916        // Hit test. Just to verify.
917        // Hit must happen, since we've just finished its' miss transaction
[434]918        bool hit = (r_tlb_buf_valid && (r_tlb_buf_tag.read()== line_number) ); 
[240]919        assert(hit and "Error: No hit on prefetch buffer after Miss Transaction"); 
920       
[434]921        entry = r_tlb_buf_data[word_position];
[240]922           
923        // Bit valid checking
924        if ( not ( entry & PTE_V_MASK) )        // unmapped
925        {
926            //must not occur!
[434]927            std::cout << "IOMMU ERROR " << name() << "TLB_IDLE state" << std::endl
[240]928                      << "The Page Table entry ins't valid (unmapped)" << std::endl;
929                       
[434]930            r_tlb_miss_error       = true;
931            r_dma_tlb_req         = false;
932            r_tlb_fsm             = TLB_IDLE;           
933
934#if DEBUG_TLB_MISS
935if ( m_debug_activated )
[240]936{
[434]937    std::cout << "  <IOB DMA_PTE1_GET> First level entry Unmapped"
938              << std::hex << " / paddr = " << r_tlb_paddr.read()
[240]939              << std::hex << " / PTE = " << entry << std::endl;
940}
941#endif
942                    break; 
943        }
944   
945        if( entry & PTE_T_MASK )        //  PTD : me must access PT2
946        {
947            // register bypass
[434]948            r_iotlb.set_bypass( r_dma_cmd_vaddr.read(),
949                                entry & ((1 << (vci_param_int::N-PAGE_K_NBITS)) - 1), 
[240]950                                0); //nline, unused
951
952            //&PTE2 = PTBA + IX2 * 8
953            // ps: PAGE_K_NBITS corresponds also to the size of a second level page table
[434]954            r_tlb_paddr = (vci_addr_t)(entry & ((1<<(vci_param_int::N-PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
955                                (vci_addr_t)(((r_dma_cmd_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
956            r_tlb_miss_req     = true;
957            r_tlb_miss_type    = PTE2_MISS;
958            r_tlb_fsm          = TLB_WAIT;
959
[240]960#ifdef INSTRUMENTATION
961m_cpt_iotlbmiss_transaction++;
962#endif
963
[434]964#if DEBUG_TLB_MISS
965if ( m_debug_activated )
966std::cout << "  <IOB TLB_PTE1_GET> Success. Search PTE2" << std::hex
967          << " / PADDR = " << r_tlb_paddr.read()
968          << " / PTD = " << entry << std::endl;
[240]969#endif
970        }
971        else                    //  PTE1 :  we must update the IOTLB
972                        //  Should not occur if working only with small pages
973        {
[434]974            r_tlb_pte_flags   = entry;
975            r_tlb_fsm  = TLB_PTE1_SELECT;
[240]976
[434]977#if DEBUG_TLB_MISS
978if ( m_debug_activated )
979std::cout << "  <IOB TLB_PTE1_GET> Success. Big page"
980          << std::hex << " / paddr = " << r_tlb_paddr.read()
981          << std::hex << " / PTE1 = " << entry << std::endl;
[240]982#endif
983        }
984        break;
985    }
[434]986    /////////////////////
987    case TLB_PTE1_SELECT:       // select a slot for PTE1
[240]988    {
989        size_t  way;
990        size_t  set;
991       
[434]992        r_iotlb.select(  r_dma_cmd_vaddr.read(),
[240]993                        true,  // PTE1
994                        &way,
995                        &set );
996#ifdef INSTRUMENTATION
997m_cpt_iotlb_read++;
998#endif
999
[434]1000#if DEBUG_TLB_MISS
1001if ( m_debug_activated )
1002std::cout << "  <IOB TLB_PTE1_SELECT> Select a slot in TLB"
1003          << " / way = " << std::dec << way
1004          << " / set = " << set << std::endl;
[240]1005#endif
[434]1006        r_tlb_way = way;
1007        r_tlb_set = set;
1008        r_tlb_fsm     = TLB_PTE1_UPDT;
[240]1009        break;
1010    }
[434]1011    ///////////////////
1012    case TLB_PTE1_UPDT:     // write a new PTE1 in tlb
1013                            // not necessary to treat the L/R bit
[240]1014    {
[434]1015        uint32_t  pte   = r_tlb_pte_flags.read();
[240]1016       
[434]1017        r_tlb_paddr = (vci_addr_t)( ((r_tlb_pte_flags.read() & PPN1_MASK) << 21)
1018                        | (r_dma_cmd_vaddr.read()& M_PAGE_OFFSET_MASK) );
[240]1019       
1020        // update TLB
1021        r_iotlb.write( true,            // 2M page
1022                      pte,
1023                      0,                // argument unused for a PTE1
[434]1024                      r_dma_cmd_vaddr.read(),   
1025                      r_tlb_way.read(), 
1026                      r_tlb_set.read(),
[240]1027                      0 );      //we set nline = 0
1028#ifdef INSTRUMENTATION
1029m_cpt_iotlb_write++;
1030#endif
1031
[434]1032#if DEBUG_TLB_MISS
1033if ( m_debug_activated )
[240]1034{
[434]1035std::cout << "  <IOB TLB_PTE1_UPDT> write PTE1 in TLB"
1036          << " / set = " << std::dec << r_tlb_set.read()
1037          << " / way = " << r_tlb_way.read() << std::endl;
1038r_iotlb.printTrace();
[240]1039}
1040#endif
1041        // next state
[434]1042        r_tlb_fsm = TLB_RETURN; // exit sub-fsm
[240]1043        break;
1044    }
[434]1045    //////////////////
1046    case TLB_PTE2_GET:  // Try to read a PTE2 (64 bits) in the miss buffer
[240]1047    {   
1048        uint32_t        pte_flags;
1049        uint32_t        pte_ppn;
1050       
[434]1051        vci_addr_t line_number  = (vci_addr_t)((r_tlb_paddr.read())&(CACHE_LINE_MASK));
1052        size_t word_position = (size_t)( ((r_tlb_paddr.read())&(~CACHE_LINE_MASK))>>2 );
[240]1053       
1054       
1055        // Hit test. Just to verify.
[434]1056        bool hit = (r_tlb_buf_valid && (r_tlb_buf_tag.read()== line_number) ); 
[240]1057        assert(hit and "Error: No hit on prefetch buffer after Miss Transaction"); 
[434]1058        pte_flags= r_tlb_buf_data[word_position];
1059        pte_ppn= r_tlb_buf_data[word_position+1]; //because PTE2 is 2 words long
[240]1060        // Bit valid checking
1061        if ( not ( pte_flags & PTE_V_MASK) )    // unmapped
1062        {
1063            //must not occur!
[434]1064            std::cout << "IOMMU ERROR " << name() << "TLB_IDLE state" << std::endl
[240]1065                      << "The Page Table entry ins't valid (unmapped)" << std::endl;
1066                       
[434]1067            r_tlb_miss_error       = true;
1068            r_dma_tlb_req         = false;
1069            r_tlb_fsm             = TLB_IDLE;           
1070
1071#if DEBUG_TLB_MISS
1072if ( m_debug_activated )
1073std::cout << "  <IOB TLB_PTE2_GET> PTE2 Unmapped" << std::hex
1074          << " / PADDR = " << r_tlb_paddr.read()
1075          << " / PTE = " << pte_flags << std::endl;
[240]1076#endif
[434]1077            break; 
[240]1078        }
1079           
[434]1080        r_tlb_pte_flags       = pte_flags; 
1081        r_tlb_pte_ppn         = pte_ppn;
1082        r_tlb_fsm           = TLB_PTE2_SELECT;
[240]1083               
[434]1084#if DEBUG_TLB_MISS
1085if ( m_debug_activated )
1086std::cout << "  <IOB TLB_PTE2_GET> Mapped" << std::hex
1087          << " / PTE_FLAGS = " << pte_flags
1088          << " / PTE_PPN = " << pte_ppn << std::endl;
[240]1089#endif
1090        break;
1091    }
1092    ////////////////////////////
[434]1093    case TLB_PTE2_SELECT:    // select a slot for PTE2
[240]1094    {
1095        size_t way;
1096        size_t set;
1097
[434]1098        r_iotlb.select( r_dma_cmd_vaddr.read(),
[240]1099                        false,  // PTE2
1100                        &way,
1101                        &set );
1102#ifdef INSTRUMENTATION
1103m_cpt_iotlb_read++;
1104#endif
1105
[434]1106#if DEBUG_TLB_MISS
1107if ( m_debug_activated )
[240]1108{
[434]1109        std::cout << "  <IOB TLB_PTE2_SELECT> Select a slot in IOTLB:";
[240]1110        std::cout << " way = " << std::dec << way
1111                  << " / set = " << set << std::endl;
1112}
1113#endif
[434]1114        r_tlb_way = way;
1115        r_tlb_set = set;
1116        r_tlb_fsm     = TLB_PTE2_UPDT;
[240]1117        break;
1118    }
[434]1119    ///////////////////
1120    case TLB_PTE2_UPDT:         // write a new PTE2 in tlb
1121                                // not necessary to treat the L/R bit
[240]1122    {
[434]1123        uint32_t        pte_flags = r_tlb_pte_flags.read();
1124        uint32_t        pte_ppn   = r_tlb_pte_ppn.read();
[240]1125       
[434]1126        r_tlb_paddr = (vci_addr_t)( ((r_tlb_pte_ppn.read() & PPN2_MASK) << 12)
1127                        | (r_dma_cmd_vaddr.read()& K_PAGE_OFFSET_MASK) );
[240]1128       
1129        // update TLB for a PTE2
1130        r_iotlb.write( false,   // 4K page
1131                       pte_flags,
1132                       pte_ppn,
[434]1133                       r_dma_cmd_vaddr.read(),   
1134                       r_tlb_way.read(), 
1135                       r_tlb_set.read(),
[240]1136                       0 );     // nline = 0
1137#ifdef INSTRUMENTATION
1138m_cpt_iotlb_write++;
1139#endif
1140
[434]1141#if DEBUG_TLB_MISS
1142if ( m_debug_activated )
[240]1143{
[434]1144        std::cout << "  <IOB TLB_PTE2_UPDT> write PTE2 in IOTLB";
1145        std::cout << " / set = " << std::dec << r_tlb_set.read()
1146                  << " / way = " << r_tlb_way.read() << std::endl;
[240]1147        r_iotlb.printTrace();
1148}
1149#endif
1150        // next state
[434]1151        r_tlb_fsm = TLB_RETURN; 
[240]1152        break;
1153    }
[434]1154    //////////////
1155    case TLB_WAIT:   // waiting completion of a miss transaction from MISS_WTI FSM
1156                     // PTE inval request are handled as unmaskable interrupts
[240]1157    {
[434]1158        if ( r_config_tlb_req ) // Request from CONFIG FSM for a PTE invalidation
[240]1159        {
1160            r_config_tlb_req = false;
1161            r_waiting_transaction = true;
[434]1162            r_tlb_fsm = TLB_INVAL_CHECK;
[240]1163        }
1164
1165#ifdef INSTRUMENTATION
1166m_cost_iotlbmiss_transaction++;
1167#endif
[434]1168        if ( not r_tlb_miss_req )       //  Miss transaction is done
[240]1169        { 
[434]1170                if ( r_miss_wti_rsp_error.read() ) // bus error
[240]1171                {
[434]1172                r_miss_wti_rsp_error = false;
1173                r_tlb_miss_error     = true;
1174                r_dma_tlb_req        = false;
1175                r_tlb_fsm            = TLB_IDLE;
[240]1176            }
1177            else if(r_tlb_miss_type == PTE1_MISS)
1178            {
[434]1179                r_tlb_fsm = TLB_PTE1_GET; 
[240]1180            }
1181            else
1182            {
[434]1183                r_tlb_fsm = TLB_PTE2_GET;
[240]1184            }
1185        }
1186        break;
1187    }
[434]1188    ////////////////
1189    case TLB_RETURN:            // reset r_dma_tlb_req flip-flop to signal TLB miss completion
1190                            // possible errors are signaled through r_tlb_miss_error
[240]1191    {
[434]1192#if DEBUG_TLB_MISS
1193if ( m_debug_activated )
1194std::cout << "  <IOB TLB_RETURN> IOTLB MISS completed" << std::endl;
[240]1195#endif
[434]1196        r_dma_tlb_req  = false;
1197        r_tlb_fsm = TLB_IDLE;
[240]1198        break;
1199    }
[434]1200    /////////////////////
1201    case TLB_INVAL_CHECK:   // request from CONFIG_FSM to invalidate all PTE in a given line
1202                            // checks the necessity to invalidate prefetch buffer
[240]1203    {
1204        // If a transaction is pending, no need to invalidate the prefetch
1205        // We can ignore it, since we'll replace the line.
1206        // The new line is necessarily up-to-date
[434]1207        if(!r_waiting_transaction.read() && r_tlb_buf_valid)
[240]1208        {
[434]1209            if(!r_tlb_buf_big_page)
[240]1210            {
[434]1211               if( r_tlb_buf_vaddr.read() == 
1212                   (r_config_cmd_inval_vaddr.read()& ~PTE2_LINE_OFFSET) ) 
[240]1213                // The virtual address corresponds to one entry on the buffer line
1214                {
[434]1215                    r_tlb_buf_valid = false;   //change here for individual invalidation
[240]1216                }
1217            }
1218            else    // First level entries on buffer. Unused if only small pages
1219            {
[434]1220               if( r_tlb_buf_vaddr.read() == 
1221                   (r_config_cmd_inval_vaddr.read()& ~PTE1_LINE_OFFSET) ) 
[240]1222                // The virtual address corresponds to one entry on the buffer line
1223                {
[434]1224                    r_tlb_buf_valid = false;   //change here for individual invalidation
[240]1225                }
1226            }
1227        }
1228       
1229        // Invalidation on IOTLB
1230        bool    ok;
[434]1231        ok = r_iotlb.inval(r_config_cmd_inval_vaddr.read());
[240]1232         
[434]1233        if(r_waiting_transaction.read()) r_tlb_fsm =TLB_WAIT; 
1234        else r_tlb_fsm = TLB_IDLE;
[240]1235        break; 
1236    }
[434]1237    } //end switch r_tlb_fsm
[240]1238   
[434]1239    ////////////////////////////////////////////////////////////////////////////////
1240    // The CONFIG_CMD_FSM handles the VCI commands from the INT network.
[585]1241    // This FSM can handle single flit config transactions, but it can also handle
1242    // software driven, multi-flits data transactions to ROM (read) or FBF (write).
1243    // The write burst transactions must be serialised from 32 to 64 bits width.
[451]1244    // The configuration requests can be local (IO_BRIDGE config registers)
1245    // or remote (config registers of peripherals on IOX network).
1246    // - The local configuration segment is identified by the "special" atribute.
1247    // - All configuration requests are checkeg against segmentation violation.
1248    // - In case of local config request, or in case of segmentation violation,
1249    //   the FSM put a VCI response request in CONFIG_RSP fifo.
[585]1250    // - In case of remote transaction, it put the VCI command in CONFIG_CMD fifo,
1251    //   and this require two cycles per IOX flit in case of write burst.
[434]1252    ///////////////////////////////////////////////////////////////////////////////
[240]1253
1254    switch( r_config_cmd_fsm.read() ) 
1255    {
[434]1256    /////////////////////
[585]1257    case CONFIG_CMD_IDLE:   // A VCI INT command is always consumed in this state
[240]1258    {
[434]1259        if ( p_vci_tgt_int.cmdval.read() ) 
[240]1260        {
[434]1261
[240]1262#if DEBUG_CONFIG_CMD
[434]1263if( m_debug_activated )
[585]1264std::cout << "  <IOB CONFIG_CMD_IDLE> ### Config Command received" << std::endl
1265          << "  address = " << std::hex << p_vci_tgt_int.address.read()
1266          << " / srcid = " << p_vci_tgt_int.srcid.read()
[434]1267          << " / trdid = " << p_vci_tgt_int.trdid.read()
1268          << " / wdata = " << std::hex << p_vci_tgt_int.wdata.read()
1269          << " / be = " << p_vci_tgt_int.be.read()
1270          << " / plen = " << std::dec << p_vci_tgt_int.plen.read()
1271          << " / eop = " << p_vci_tgt_int.eop.read() << std::endl;
[240]1272#endif
[434]1273            vci_addr_t paddr = p_vci_tgt_int.address.read();
1274            bool       read  = (p_vci_tgt_int.cmd.read() == vci_param_int::CMD_READ);
1275            uint32_t   cell  = (uint32_t)((paddr & 0x1FF)>>2); 
[585]1276            bool       eop   = p_vci_tgt_int.eop.read();
1277            bool       high  = (paddr & 0x4);
1278
[451]1279            // chek segments
1280            std::list<soclib::common::Segment>::iterator seg;
[549]1281            bool found   = false;
1282            bool special = false;
[451]1283            for ( seg = m_int_seglist.begin() ; 
1284                  seg != m_int_seglist.end() and not found ; seg++ )
1285            {
[549]1286                if ( seg->contains(paddr) ) 
1287                {
1288                   found   = true;
1289                   special = seg->special();
1290                }
[451]1291            }
[434]1292           
[549]1293            if ( found and special )  // IO_BRIDGE itself
[240]1294            {
[585]1295                bool rerror = false;
[434]1296
[585]1297                assert( (p_vci_tgt_int.be.read() == 0xF) and
1298                "ERROR in vci_io_bridge : BE != 0xF for a config access");
1299
1300                assert( ( eop ) and
1301                "ERROR in vci_io_bridge : local config access must be one flit");
1302
[434]1303                if ( not read && (cell == IOB_IOMMU_PTPR) )       // WRITE PTPR
[240]1304                {
[434]1305                    r_iommu_ptpr = (uint32_t)p_vci_tgt_int.wdata.read();
1306                }
1307                else if ( read && (cell == IOB_IOMMU_PTPR) )      // READ PTPR
[240]1308                {
[585]1309                    r_config_cmd_rdata = r_iommu_ptpr.read();
[240]1310                }
[434]1311                else if( not read && (cell == IOB_WTI_ENABLE))  // WRITE WTI_ENABLE
[240]1312                {
[434]1313                    r_iommu_wti_enable = p_vci_tgt_int.wdata.read();
[240]1314                }
[434]1315                else if( read && (cell == IOB_WTI_ENABLE))       // READ WTI ENABLE
[240]1316                {
[585]1317                    r_config_cmd_rdata = r_iommu_wti_enable.read();
[240]1318                }
[434]1319                else if( read && (cell == IOB_IOMMU_BVAR))        // READ BVAR
[240]1320                {
[585]1321                    r_config_cmd_rdata = r_iommu_bvar.read();
[240]1322                }
[434]1323                else if( read && (cell == IOB_IOMMU_ETR))          // READ ETR
[240]1324                {
[585]1325                    r_config_cmd_rdata = r_iommu_etr.read();
[240]1326                }
[434]1327                else if( read && (cell == IOB_IOMMU_BAD_ID))      // READ BAD_ID
[240]1328                {
[585]1329                    r_config_cmd_rdata = r_iommu_bad_id.read();
[240]1330                }
[434]1331                else if( not read && (cell == IOB_INVAL_PTE))     // WRITE INVAL_PTE
[240]1332                {
[434]1333                    r_config_tlb_req         = true;
1334                    r_config_cmd_inval_vaddr = (uint32_t)p_vci_tgt_int.wdata.read();
[240]1335                }
[434]1336                else if( not read && (cell == IOB_WTI_ADDR_LO)) // WRITE WTI_PADDR_LO
[240]1337                {
[434]1338                    r_iommu_wti_paddr = (vci_addr_t)p_vci_tgt_int.wdata.read();
[240]1339                }
[434]1340                else if( read && (cell == IOB_WTI_ADDR_LO))    // READ WTI_PADDR_LO
[240]1341                {
[585]1342                    r_config_cmd_rdata = (uint32_t)r_iommu_wti_paddr.read();
[240]1343                }
[434]1344                else if( not read && (cell == IOB_WTI_ADDR_HI)) // WRITE WTI_PADDR_HI
[240]1345                {
[434]1346                    r_iommu_wti_paddr = (r_iommu_wti_paddr.read() & 0x00000000FFFFFFFFLL) |
1347                                        ((vci_addr_t)p_vci_tgt_int.wdata.read())<<32;
[240]1348                }
[434]1349                else if( read && (cell == IOB_WTI_ADDR_HI))    // READ WTI_PADDR_HI
[240]1350                {
[585]1351                    r_config_cmd_rdata = (uint32_t)(r_iommu_wti_paddr.read()>>32);
[240]1352                }
[434]1353                else if( not read && ((cell >= IOB_PERI_WTI_BEGIN)  // WRITE PERI WTI
1354                          && (cell< (IOB_PERI_WTI_BEGIN + 64))) )
1355                {
1356                    size_t  index = (cell - IOB_PERI_WTI_BEGIN)/2;
1357                    bool    high  = (cell - IOB_PERI_WTI_BEGIN)%2;
1358                    if ( high ) r_iommu_peri_wti[index] =          // set 32 MSB bits
1359                        (r_iommu_peri_wti[index].read() & 0x00000000FFFFFFFFLL) |
1360                        ((vci_addr_t)p_vci_tgt_int.wdata.read())<<32;
1361                    else        r_iommu_peri_wti[index] =          // set 32 LSB bits
1362                         (vci_addr_t)p_vci_tgt_int.wdata.read();
1363                } 
1364                else if( read && ((cell >= IOB_PERI_WTI_BEGIN)      // READ PERI WTI   
1365                         && (cell< (IOB_PERI_WTI_BEGIN + 64))) ) 
1366                {
1367                    size_t  index = (cell - IOB_PERI_WTI_BEGIN)/2;
1368                    bool    high  = (cell - IOB_PERI_WTI_BEGIN)%2;
[585]1369                    if ( high ) r_config_cmd_rdata = 
1370                                    (uint32_t)(r_iommu_peri_wti[index].read()>>32);
1371                    else        r_config_cmd_rdata = 
1372                                    (uint32_t)(r_iommu_peri_wti[index].read());
[434]1373                }
1374                else   // Error: Wrong address, or invalid operation.
1375                {
1376                    rerror = true;
1377                }
1378                r_config_cmd_error = rerror;
[585]1379                r_config_cmd_fsm   = CONFIG_CMD_RSP;
[240]1380            }
[451]1381            else if ( found )                            // remote peripheral
[240]1382            {
[585]1383                r_config_cmd_address = p_vci_tgt_int.address.read();
1384                r_config_cmd_srcid   = p_vci_tgt_int.srcid.read();
1385                r_config_cmd_trdid   = p_vci_tgt_int.trdid.read();
1386                r_config_cmd_pktid   = p_vci_tgt_int.pktid.read();
1387                r_config_cmd_pktid   = p_vci_tgt_int.pktid.read();
1388                r_config_cmd_plen    = p_vci_tgt_int.plen.read();
1389                r_config_cmd_cmd     = p_vci_tgt_int.cmd.read();
1390                r_config_cmd_cons    = p_vci_tgt_int.cons.read();
1391                r_config_cmd_clen    = p_vci_tgt_int.clen.read();
1392                r_config_cmd_wrap    = p_vci_tgt_int.wrap.read();
1393                r_config_cmd_contig  = p_vci_tgt_int.contig.read();
1394                r_config_cmd_cfixed  = p_vci_tgt_int.cfixed.read();
1395
1396                if( eop )                                // single flit command
1397                {
1398                    if ( high )     // HI word
1399                    {
1400                        r_config_cmd_wdata = ((ext_data_t)p_vci_tgt_int.wdata.read())<<32;
1401                        r_config_cmd_be    = ((ext_be_t)p_vci_tgt_int.be.read())<<4;
1402                        r_config_cmd_eop   = true;
1403                        r_config_cmd_fsm   = CONFIG_CMD_PUT;
1404                    }
1405                    else            // LO word
1406                    {
1407                        r_config_cmd_wdata = ((ext_data_t)p_vci_tgt_int.wdata.read());
1408                        r_config_cmd_be    = ((ext_be_t)p_vci_tgt_int.be.read());
1409                        r_config_cmd_eop   = true;
1410                        r_config_cmd_fsm   = CONFIG_CMD_PUT;
1411                    }
1412                }
1413                else                                     // multi-flits write
1414                {
1415                    if ( high )     // MSB word
1416                    {
1417                        r_config_cmd_wdata = ((ext_data_t)p_vci_tgt_int.wdata.read())<<32;
1418                        r_config_cmd_be    = ((ext_be_t)p_vci_tgt_int.be.read())<<4;
1419                        r_config_cmd_eop   = false;
1420                        r_config_cmd_fsm   = CONFIG_CMD_PUT;
1421                    }
1422                    else            // LSB word
1423                    {
1424                        r_config_cmd_wdata = ((ext_data_t)p_vci_tgt_int.wdata.read());
1425                        r_config_cmd_be    = ((ext_be_t)p_vci_tgt_int.be.read());
1426                        r_config_cmd_eop   = false;
1427                        r_config_cmd_fsm   = CONFIG_CMD_NEXT;
1428                    }
1429                }
[240]1430            }
[585]1431            else                                         // out of segment address
[451]1432            {
[585]1433                r_config_cmd_rdata  = 0;
[451]1434                r_config_cmd_error = true;
[585]1435                if( eop ) r_config_cmd_fsm = CONFIG_CMD_RSP;
[451]1436            }
[434]1437        } // end if cmdval
[240]1438        break;
1439    }
[585]1440    /////////////////////
1441    case CONFIG_CMD_NEXT:  // Consume the second flit for a multi-flits write
[240]1442    {
[585]1443        if ( p_vci_tgt_int.cmdval.read() ) 
1444        {
1445            vci_addr_t paddr = p_vci_tgt_int.address.read();
1446            bool       high  = (paddr & 0x4 == 0x4);
1447            bool       eop   = p_vci_tgt_int.eop.read();
1448
1449            assert( (paddr == r_config_cmd_address.read() + 4) and high and
1450            "ERROR in vci_io_bridge : addresses must be contiguous in write burst" );
1451
1452            r_config_cmd_wdata = r_config_cmd_wdata.read() |
1453                                 ((ext_data_t)p_vci_tgt_int.wdata.read()<<32);
1454            r_config_cmd_be    = r_config_cmd_be.read() |
1455                                 ((ext_be_t)p_vci_tgt_int.be.read()<<4);
1456            r_config_cmd_eop   = eop;
1457            r_config_cmd_fsm   = CONFIG_CMD_PUT;
1458        }
1459        break;
1460    }
1461    ////////////////////
1462    case CONFIG_CMD_PUT:   // try to post a command to CONFIG_CMD fifo (to IOX network)
1463    {
[434]1464        config_cmd_fifo_put = true;
1465
[585]1466        if ( m_config_cmd_addr_fifo.wok() )
[240]1467        {
[434]1468
1469#if DEBUG_CONFIG_CMD
1470if( m_debug_activated ) 
[585]1471std::cout << "  <IOB CONFIG_CMD_PUT> Transmit VCI command to IOX network"
1472          << " : address = " << std::hex << r_config_cmd_address.read()
1473          << " / srcid = " << r_config_cmd_srcid.read()
1474          << " / eop = " << r_config_cmd_eop.read()
[434]1475          << std::endl;
1476#endif
[585]1477            r_config_cmd_fsm = CONFIG_CMD_IDLE;
[434]1478        }
1479        break;
[240]1480    }
[585]1481    ////////////////////
1482    case CONFIG_CMD_RSP:   // Try to put a response in CONFIG_RSP fifo, for
1483                           // a local configuration transaction or a segment error.
1484                           // The FIFO is shared with CONFIG_RSP FSM
1485                           // and must we wait for allocation...
[240]1486    {
[585]1487        if ( r_alloc_fifo_config_rsp_local.read() )
[240]1488        {
[434]1489            config_rsp_fifo_put = true;
1490
1491            if ( m_config_rsp_data_fifo.wok() ) 
1492            {
1493
1494#if DEBUG_CONFIG_CMD
1495if( m_debug_activated ) 
[585]1496std::cout << "  <IOB CONFIG_CMD_RSP> Response to a local configuration request" 
[434]1497          << std::endl;
1498#endif
[585]1499                r_config_cmd_fsm = CONFIG_CMD_IDLE;
[434]1500            }
[240]1501        }
1502        break;
1503    }
1504    } // end switch CONFIG_CMD FSM
1505
1506    //////////////////////////////////////////////////////////////////////////////
[585]1507    // The CONFIG_RSP_FSM handles the 64 bits VCI responses from the periherals
[434]1508    // on the IOX network and  writes the responses in the CONFIG_RSP fifo.
[585]1509    // This FSM handle both single flit config responses, and multi-flits
1510    // read responses (ROM), where data must be serialised (64 bits -> 32 bits).
1511    // Note: We use the VCI RPKTID field to distinguish between read cached
1512    // (multi-flits response) and others (single flit response).
1513    // The VCI response flit is only consumed in the PUT_UNC or PUT_HI states.
[434]1514    //////////////////////////////////////////////////////////////////////////////
1515
[240]1516    switch( r_config_rsp_fsm.read() ) 
1517    {
1518    /////////////////////
[434]1519    case CONFIG_RSP_IDLE:  // waiting a VCI response from IOX network
[585]1520                           // flit on IOX network is not consumed
[240]1521    {           
[434]1522        if ( p_vci_ini_iox.rspval.read() ) 
[240]1523                {
[585]1524            if ( (p_vci_ini_iox.rpktid.read() & 0x5) == 0x1 )   // multi-flits response
1525            {
1526                r_config_rsp_fsm   = CONFIG_RSP_PUT_LO;
1527            }
1528            else                                                // single flit response
1529            {
1530                r_config_rsp_fsm   = CONFIG_RSP_PUT_UNC;
1531               
1532                assert(  p_vci_ini_iox.reop.read() and
1533                "ERROR in vci_io_bridge : a remote config response should be one flit");
1534            }
[240]1535                }
1536                break;
1537    }
[585]1538    ///////////////////////
1539    case CONFIG_RSP_PUT_LO:   // try to write 32 low bits into CONFIG_RSP fifo
1540                              // flit on IOX network is not consumed
[240]1541    {
[585]1542        if ( not r_alloc_fifo_config_rsp_local.read() and  m_config_rsp_data_fifo.wok() )       
1543        {
1544            r_config_rsp_fsm   = CONFIG_RSP_PUT_HI;
[240]1545
[585]1546#if DEBUG_CONFIG_RSP
1547if( m_debug_activated ) 
1548std::cout << "  <IOB CONFIG_RSP_PUT_LO> Push multi-flit response into CONFIG_RSP fifo:" 
1549          << " / rsrcid = " << std::hex << p_vci_ini_iox.rsrcid.read()
1550          << " / rtrdid = " << p_vci_ini_iox.rtrdid.read()
1551          << " / rpktid = " << p_vci_ini_iox.rpktid.read()
1552          << " / rdata = " << (uint32_t)p_vci_ini_iox.rdata.read()
1553          << " / reop  = " << false
1554          << " / rerror = " << p_vci_ini_iox.rerror.read() << std::endl;
1555#endif
1556        }
1557        break;
1558    }
1559    ///////////////////////
1560    case CONFIG_RSP_PUT_HI:    // try to write 32 high bits into CONFIG_RSP fifo
1561                               // flit on IOX network is consumed if success
1562    {
1563        if ( not r_alloc_fifo_config_rsp_local.read() and  m_config_rsp_data_fifo.wok() )       
1564        {
1565            if( p_vci_ini_iox.reop.read() )    r_config_rsp_fsm = CONFIG_RSP_IDLE;
1566            else                               r_config_rsp_fsm = CONFIG_RSP_PUT_LO;
[434]1567
[240]1568#if DEBUG_CONFIG_RSP
[434]1569if( m_debug_activated ) 
[585]1570std::cout << "  <IOB CONFIG_RSP_PUT_HI> Push multi-flit response into CONFIG_RSP fifo:" 
[434]1571          << " / rsrcid = " << std::hex << p_vci_ini_iox.rsrcid.read()
1572          << " / rtrdid = " << p_vci_ini_iox.rtrdid.read()
[585]1573          << " / rpktid = " << p_vci_ini_iox.rpktid.read()
1574          << " / rdata = " << (uint32_t)(p_vci_ini_iox.rdata.read()>>32)
[434]1575          << " / reop  = " << p_vci_ini_iox.reop.read()
1576          << " / rerror = " << p_vci_ini_iox.rerror.read() << std::endl;
[240]1577#endif
1578        }
1579        break;
1580    }
[585]1581    ////////////////////////
1582    case CONFIG_RSP_PUT_UNC:   // try to write single flit into CONFIG_RSP fifo
1583                               // flit on IOX network is consumed if success
1584    {
1585        if ( not r_alloc_fifo_config_rsp_local.read() and  m_config_rsp_data_fifo.wok() )       
1586        {
1587            r_config_rsp_fsm   = CONFIG_RSP_IDLE;
1588
1589#if DEBUG_CONFIG_RSP
1590if( m_debug_activated ) 
1591std::cout << "  <IOB CONFIG_RSP_PUT_UNC> Push single flit response into CONFIG_RSP fifo:" 
1592          << " / rsrcid = " << std::hex << p_vci_ini_iox.rsrcid.read()
1593          << " / rtrdid = " << p_vci_ini_iox.rtrdid.read()
1594          << " / rpktid = " << p_vci_ini_iox.rpktid.read()
1595          << " / rdata = " << (uint32_t)p_vci_ini_iox.rdata.read()
1596          << " / reop  = " << true
1597          << " / rerror = " << p_vci_ini_iox.rerror.read() << std::endl;
1598#endif
1599        }
1600        break;
1601    }
[240]1602    } // end switch CONFIG_RSP FSM
1603
[434]1604    /////////////////////////////////////////////////////////////////////////////////
1605    // If the IOB component has IRQ ports, the IRQ FSM detects all changes
1606    // on the 32 p_irq[i] ports and request a VCI write transaction to the
1607    // MISS_INIT FSM, using the 64 r_irq_request[i] and r_irq_pending[i] flip-flops.
1608    /////////////////////////////////////////////////////////////////////////////////
[240]1609
[434]1610    if ( m_has_irqs )
[240]1611    {
[434]1612        for ( size_t i = 0; i<32; ++i )
[240]1613        {
[434]1614            r_irq_request[i] = ( p_irq[i]->read() == not r_irq_pending[i].read() );
1615            r_irq_pending[i] = p_irq[i]->read();
[240]1616        }
1617    }
[434]1618       
1619    ///////////////////////////////////////////////////////////////////////////////////
1620    // The MISS_WTI_CMD FSM send VCI commands on the Internal Network.
1621    // It handles PTE MISS requests from TLB_MISS FSM and software IRQs.
1622    // It supports several simultaneous VCI transactions.
[240]1623    ////////////////////////////////////////////////////////////////////////////////////
1624 
[434]1625    switch ( r_miss_wti_cmd_fsm.read() ) 
[240]1626    {
[434]1627        ///////////////////////
1628        case MISS_WTI_CMD_IDLE:   // TLB MISS have highest priority
[240]1629        {
[434]1630            if ( r_tlb_miss_req.read() )
[240]1631            {
[434]1632                r_miss_wti_cmd_fsm = MISS_WTI_CMD_MISS;
[240]1633            }
[434]1634            else if ( r_iommu_wti_enable.read() )
1635            {
1636                // checking if there is a new pending interrupt
[240]1637                bool found = false;
[434]1638                size_t n;
1639                for ( n = 0 ; (n < 32) and not found ; n++ )
[240]1640                {
[434]1641                    if ( r_irq_request[n] ) found = true;
[240]1642                }
[434]1643                if ( found )
1644                {
1645                    r_miss_wti_cmd_index = n;
1646                    r_miss_wti_cmd_fsm   = MISS_WTI_CMD_WTI;
1647                }
[240]1648            }
1649                        break;
1650        }
[434]1651        //////////////////////     
1652        case MISS_WTI_CMD_WTI:   // send a single flit IRQ WRITE on INT Network
1653                                 // address is defined by IRQ_VECTOR[r_miss_wti_index]
1654                                 // data is defined by r_irq_pending[r_miss_wti_index]
[240]1655        {
[434]1656            if ( p_vci_ini_int.cmdack ) 
1657            {
1658                // reset the request
1659                r_irq_request[r_miss_wti_cmd_index.read()] = false;
1660                r_miss_wti_cmd_fsm = MISS_WTI_RSP_WTI;         
[240]1661
[434]1662#if DEBUG_MISS_WTI
1663if( m_debug_activated )
1664std::cout << "  <IOB MISS_WTI_CMD_WTI> Send WTI write command on Internal Network"
1665          << " / IRQID = " << std::dec << r_miss_wti_cmd_index.read() << std::endl;
1666#endif
[240]1667            }
[434]1668            break;
[240]1669        }
[434]1670        ///////////////////////
1671        case MISS_WTI_CMD_MISS:   // send a TLB MISS request on INT Network
[240]1672        {
[434]1673            if ( p_vci_ini_int.cmdack ) 
1674            {
1675                r_tlb_buf_tag     = ( (r_tlb_paddr.read()) & CACHE_LINE_MASK ); 
1676                r_tlb_buf_valid   = true;
1677           
1678                if( r_tlb_miss_type.read() == PTE1_MISS )
1679                    r_tlb_buf_vaddr = (r_dma_cmd_vaddr.read() & 
1680                                        ~M_PAGE_OFFSET_MASK & ~PTE1_LINE_OFFSET);
1681                else
1682                    r_tlb_buf_vaddr = (r_dma_cmd_vaddr.read() & 
1683                                        ~K_PAGE_OFFSET_MASK & ~PTE2_LINE_OFFSET);
1684               
1685                r_miss_wti_cmd_fsm = MISS_WTI_RSP_MISS;         
[240]1686
[434]1687#if DEBUG_MISS_WTI
1688if( m_debug_activated )
1689std::cout << "  <IOB MISS_WTI_CMD_MISS> Send TLB MISS command on Internal Network" << std::hex
1690          << " / address = " <<(vci_addr_t)((r_tlb_paddr.read())& CACHE_LINE_MASK) << std::endl;
[240]1691#endif
[434]1692            }
[240]1693            break;
1694        }
[434]1695    } // end switch r_miss_wti_cmd_fsm
1696
1697    ///////////////////////////////////////////////////////////////////////////////////
1698    // The MISS_WTI_RSP FSM handles VCI responses on the Internal Network.
1699    // it can be response to TLB MISS (read transaction) or WTI (write transaction).
1700    // It supports several simultaneous VCI transactions.
1701    ////////////////////////////////////////////////////////////////////////////////////
1702 
1703    switch ( r_miss_wti_rsp_fsm.read() ) 
1704    {
1705        case MISS_WTI_RSP_IDLE:   // waiting a VCI response
[240]1706        {
[434]1707            if ( p_vci_ini_int.rspval.read() ) 
[240]1708            {
[434]1709                if ( p_vci_ini_int.rpktid.read() == PKTID_READ )  // it's a TLB MISS response
[240]1710                {
[434]1711                    r_miss_wti_rsp_fsm   = MISS_WTI_RSP_MISS;
1712                    r_miss_wti_rsp_count = 0;
[240]1713                }
[434]1714                else                                       // it's a WTI WRITE response
1715                {
1716                    r_miss_wti_rsp_fsm   = MISS_WTI_RSP_WTI;
1717
1718                }
[240]1719            }
1720            break;
1721        }
[434]1722        //////////////////////
1723        case MISS_WTI_RSP_WTI:   // Handling response to a WTI transaction
[240]1724        {
[434]1725            assert( p_vci_ini_int.reop.read() and
1726            "VCI_IO_BRIDGE ERROR: IRQ Write response should have one single flit" ); 
[240]1727
[434]1728            assert( ( (p_vci_ini_int.rerror.read()&0x1) == 0 ) and
1729            "VCI_IO_BRIDGE ERROR: IRQ Write response error !!!" ); 
[585]1730             // TODO handling error when using the IOMMU IRQ
[434]1731
1732#if DEBUG_MISS_WTI
1733if( m_debug_activated )
1734std::cout << "  <IOB MISS_WTI_RSP_WTI> Response to WTI write" << std::endl;
[240]1735#endif
[434]1736            r_miss_wti_rsp_fsm = MISS_WTI_RSP_IDLE;
[240]1737            break;
1738        }
[434]1739        ///////////////////////
1740        case MISS_WTI_RSP_MISS:   // Handling response to a TLB MISS transaction
[240]1741        {
[434]1742            if ( p_vci_ini_int.rspval.read() ) 
[240]1743            {
[434]1744                if ( (p_vci_ini_int.rerror.read()&0x1) != 0 )  // error reported
[240]1745                {
[434]1746                    r_miss_wti_rsp_error = true;
1747                    if ( p_vci_ini_int.reop.read() ) 
[240]1748                    {   
[434]1749                        r_miss_wti_cmd_fsm = MISS_WTI_RSP_IDLE;
1750                        r_tlb_miss_req = false; 
[240]1751                    }
[434]1752#if DEBUG_MISS_WTI
1753if( m_debug_activated ) 
1754std::cout << " <IOB MISS_WTI_RSP_MISS> ERROR " << std::endl; 
[240]1755#endif
1756                }
[434]1757                else                                           // no error
[240]1758                { 
[434]1759                    bool   eop          = p_vci_ini_int.reop.read();
[240]1760
[434]1761#if DEBUG_MISS_WTI
1762if( m_debug_activated ) 
1763std::cout << "  <IOB MISS_WTI_RSP_MISS> Response to a tlb miss transaction"
1764          << " / Count = " << r_miss_wti_rsp_count.read()
1765          << " / Data = " << std::hex << p_vci_ini_int.rdata.read() << std::endl; 
[240]1766#endif
[434]1767                    assert(((eop == (r_miss_wti_rsp_count.read() == (m_words-1)))) and
1768                    "VCI_IO_BRIDGE ERROR: invalid length for a TLB MISS response");
[240]1769
[434]1770                    r_tlb_buf_data[r_miss_wti_rsp_count.read()] = p_vci_ini_int.rdata.read();
1771                    r_miss_wti_rsp_count = r_miss_wti_rsp_count.read() + 1;
[240]1772                   
1773                    if ( eop ) 
1774                    {
[434]1775                        r_tlb_miss_req = false;     //reset the request flip-flop
1776                        r_miss_wti_cmd_fsm = MISS_WTI_RSP_IDLE;         
[240]1777                    }
1778                }
1779            }
1780            break;
1781        }
[434]1782    } // end  switch r_miss_wti_rsp_fsm
[240]1783
[434]1784    /////////////////////////////////////////////////////////////////////////
1785    // This flip-flop allocates the access to the CONFIG_RSP fifo
1786    // with a round robin priority between 2 clients FSMs :
1787    // - CONFIG_CMD : to put a response to a local config command.
1788    // - CONFIG_RSP : to put a response to a peripheral config command.
1789    // The ressource is always allocated.
1790    // A new allocation occurs when the owner FSM is not using it,
1791    // and the other FSM is requiring it.
1792    /////////////////////////////////////////////////////////////////////////
[240]1793   
[434]1794    if ( r_alloc_fifo_config_rsp_local.read() )
[240]1795    {
[585]1796        if ( (r_config_rsp_fsm.read() != CONFIG_RSP_IDLE) and   // config_rsp_fsm requiring
1797             (r_config_cmd_fsm.read() != CONFIG_CMD_RSP) )      // config_cmd_fsm not requiring
[434]1798        r_alloc_fifo_config_rsp_local = false;
[240]1799    }
[434]1800    else 
[240]1801    {
[585]1802        if ( (r_config_cmd_fsm.read() == CONFIG_CMD_RSP) and    // config_cmd_fsm requiring
1803             (r_config_rsp_fsm.read() == CONFIG_RSP_IDLE) )     // config_rsp_fsm not requiring
[434]1804        r_alloc_fifo_config_rsp_local = true;
[240]1805    }
[434]1806
1807    /////////////////////////////////////////////////////////////////////////
1808    // This flip-flop allocates the access to the DMA_RSP fifo
1809    // with a round robin priority between 2 clients FSMs :
1810    // - DMA_CMD : to put a error response in case of bad address translation
1811    // - DMA_RSP : to put a normal response to a DMA transaction.
1812    // The ressource is always allocated.
1813    // A new allocation occurs when the owner FSM is not using it,
1814    // and the other FSM is requiring it.
1815    /////////////////////////////////////////////////////////////////////////
1816   
1817    if ( r_alloc_fifo_dma_rsp_local.read() )
[240]1818    {
[434]1819        if ( (r_dma_rsp_fsm.read() == DMA_RSP_FIFO_PUT) and
1820             (r_dma_cmd_fsm.read() != DMA_CMD_FIFO_PUT_RSP) )
1821        r_alloc_fifo_dma_rsp_local = false;
[240]1822    }
1823    else 
1824    {
[434]1825        if ( (r_dma_cmd_fsm.read() == DMA_CMD_FIFO_PUT_RSP) and
1826             (r_dma_rsp_fsm.read() != DMA_RSP_FIFO_PUT) )
1827        r_alloc_fifo_dma_rsp_local = true;
[240]1828    }
1829
[434]1830    // Define GET signals for all output FIFOs
1831    dma_cmd_fifo_get    = p_vci_ini_ram.cmdack.read();
1832    dma_rsp_fifo_get    = p_vci_tgt_iox.rspack.read();
1833    config_cmd_fifo_get = p_vci_ini_iox.cmdack.read();
1834    config_rsp_fifo_get = p_vci_tgt_int.rspack.read();
1835
1836    ///////////////////////////////////////////////////////////
1837    // DMA_CMD fifo update
1838    // One writer : DMA_CMD FSM
1839    ///////////////////////////////////////////////////////////
1840
1841    m_dma_cmd_addr_fifo.update(   dma_cmd_fifo_get,
1842                                  dma_cmd_fifo_put,
1843                                  r_dma_cmd_paddr.read() );   // address translation
1844    m_dma_cmd_cmd_fifo.update(    dma_cmd_fifo_get,
1845                                  dma_cmd_fifo_put,
1846                                  p_vci_tgt_iox.cmd.read() );
1847    m_dma_cmd_contig_fifo.update( dma_cmd_fifo_get,
1848                                  dma_cmd_fifo_put,
1849                                  p_vci_tgt_iox.contig.read() );
1850    m_dma_cmd_cons_fifo.update(   dma_cmd_fifo_get,
1851                                  dma_cmd_fifo_put,
1852                                  p_vci_tgt_iox.cons.read() );
1853    m_dma_cmd_plen_fifo.update(   dma_cmd_fifo_get,
1854                                  dma_cmd_fifo_put,
1855                                  p_vci_tgt_iox.plen.read() );
1856    m_dma_cmd_wrap_fifo.update(   dma_cmd_fifo_get,
1857                                  dma_cmd_fifo_put,
1858                                  p_vci_tgt_iox.wrap.read() );
1859    m_dma_cmd_cfixed_fifo.update( dma_cmd_fifo_get,
1860                                  dma_cmd_fifo_put,
1861                                  p_vci_tgt_iox.cfixed.read() );
1862    m_dma_cmd_clen_fifo.update(   dma_cmd_fifo_get,
1863                                  dma_cmd_fifo_put,
1864                                  p_vci_tgt_iox.clen.read() );
1865    m_dma_cmd_srcid_fifo.update(  dma_cmd_fifo_get,
1866                                  dma_cmd_fifo_put,
1867                                  p_vci_tgt_iox.srcid.read() );
1868    m_dma_cmd_trdid_fifo.update(  dma_cmd_fifo_get,
1869                                  dma_cmd_fifo_put,
1870                                  p_vci_tgt_iox.trdid.read() );
1871    m_dma_cmd_pktid_fifo.update(  dma_cmd_fifo_get,
1872                                  dma_cmd_fifo_put,
1873                                  p_vci_tgt_iox.pktid.read() );
1874    m_dma_cmd_data_fifo.update(   dma_cmd_fifo_get,
1875                                  dma_cmd_fifo_put,
1876                                  p_vci_tgt_iox.wdata.read() ); 
1877    m_dma_cmd_be_fifo.update(     dma_cmd_fifo_get,
1878                                  dma_cmd_fifo_put,
1879                                  p_vci_tgt_iox.be.read() ); 
1880    m_dma_cmd_eop_fifo.update(    dma_cmd_fifo_get,
1881                                  dma_cmd_fifo_put,
1882                                  p_vci_tgt_iox.eop.read() );
1883
1884    //////////////////////////////////////////////////////////////
1885    // DMA_RSP fifo update
1886    // Two writers : DMA_CMD FSM & DMA_RSP FSM
1887    //////////////////////////////////////////////////////////////
1888
1889    if (r_alloc_fifo_dma_rsp_local.read() )  // owner is DMA_CMD FSM
1890                                             // local response for a translation error
[240]1891    {
[434]1892        m_dma_rsp_data_fifo.update(   dma_rsp_fifo_get,
1893                                      dma_rsp_fifo_put,
1894                                      0 );                      // no data if error
[240]1895        m_dma_rsp_rsrcid_fifo.update( dma_rsp_fifo_get,
[434]1896                                      dma_rsp_fifo_put,
1897                                      p_vci_tgt_iox.rsrcid.read() ); 
[240]1898        m_dma_rsp_rtrdid_fifo.update( dma_rsp_fifo_get,
[434]1899                                      dma_rsp_fifo_put,
1900                                      p_vci_tgt_iox.rtrdid.read() ); 
[240]1901        m_dma_rsp_rpktid_fifo.update( dma_rsp_fifo_get,
[434]1902                                      dma_rsp_fifo_put,
1903                                      p_vci_tgt_iox.rpktid.read() ); 
1904        m_dma_rsp_reop_fifo.update(   dma_rsp_fifo_get,
1905                                      dma_rsp_fifo_put,
1906                                      true );                    // single flit response
[240]1907        m_dma_rsp_rerror_fifo.update( dma_rsp_fifo_get,
1908                                      dma_rsp_fifo_put,
[434]1909                                      1 );                        // error
[240]1910    }
[434]1911    else                                   // owner is DMA_RSP FSM
1912                                           // normal response to a DMA transaction
[240]1913    {
[434]1914        m_dma_rsp_data_fifo.update(   dma_rsp_fifo_get,
1915                                      dma_rsp_fifo_put,
1916                                      p_vci_ini_ram.rdata.read() );
[240]1917        m_dma_rsp_rsrcid_fifo.update( dma_rsp_fifo_get,
[434]1918                                      dma_rsp_fifo_put,
1919                                      p_vci_ini_ram.rsrcid.read() );
[240]1920        m_dma_rsp_rtrdid_fifo.update( dma_rsp_fifo_get,
[434]1921                                      dma_rsp_fifo_put,
1922                                      p_vci_ini_ram.rtrdid.read() );
[240]1923        m_dma_rsp_rpktid_fifo.update( dma_rsp_fifo_get,
[434]1924                                      dma_rsp_fifo_put,
1925                                      p_vci_ini_ram.rpktid.read() );
1926        m_dma_rsp_reop_fifo.update(   dma_rsp_fifo_get,
1927                                      dma_rsp_fifo_put,
1928                                      p_vci_ini_ram.reop.read() );
[240]1929        m_dma_rsp_rerror_fifo.update( dma_rsp_fifo_get,
1930                                      dma_rsp_fifo_put,
[434]1931                                      p_vci_ini_ram.rerror.read() );
[240]1932    }
1933
[434]1934    ////////////////////////////////////////////////////////////////
1935    // CONFIG_CMD fifo update
1936    // One writer : CONFIG_CMD FSM
1937    ////////////////////////////////////////////////////////////////
1938
1939    m_config_cmd_addr_fifo.update(   config_cmd_fifo_get,
1940                                     config_cmd_fifo_put,
[585]1941                                     r_config_cmd_address.read() ); 
[434]1942    m_config_cmd_cmd_fifo.update(    config_cmd_fifo_get,
1943                                     config_cmd_fifo_put,
[585]1944                                     r_config_cmd_cmd.read() ); 
[240]1945    m_config_cmd_contig_fifo.update( config_cmd_fifo_get,
[434]1946                                     config_cmd_fifo_put,
[585]1947                                     r_config_cmd_contig.read() ); 
[434]1948    m_config_cmd_cons_fifo.update(   config_cmd_fifo_get,
1949                                     config_cmd_fifo_put,
[585]1950                                     r_config_cmd_cons.read() ); 
[434]1951    m_config_cmd_plen_fifo.update(   config_cmd_fifo_get,
1952                                     config_cmd_fifo_put,
[585]1953                                     r_config_cmd_plen.read() ); 
[434]1954    m_config_cmd_wrap_fifo.update(   config_cmd_fifo_get,
1955                                     config_cmd_fifo_put,
[585]1956                                     r_config_cmd_wrap.read() ); 
[240]1957    m_config_cmd_cfixed_fifo.update( config_cmd_fifo_get,
[434]1958                                     config_cmd_fifo_put,
[585]1959                                     r_config_cmd_cfixed.read() ); 
[434]1960    m_config_cmd_clen_fifo.update(   config_cmd_fifo_get,
1961                                     config_cmd_fifo_put,
[585]1962                                     r_config_cmd_clen.read() ); 
[434]1963    m_config_cmd_srcid_fifo.update(  config_cmd_fifo_get,
1964                                     config_cmd_fifo_put,
[585]1965                                     r_config_cmd_srcid.read() );
[434]1966    m_config_cmd_trdid_fifo.update(  config_cmd_fifo_get,
1967                                     config_cmd_fifo_put,
[585]1968                                     r_config_cmd_trdid.read() );
[434]1969    m_config_cmd_pktid_fifo.update(  config_cmd_fifo_get,
1970                                     config_cmd_fifo_put,
[585]1971                                     r_config_cmd_pktid.read() );
[434]1972    m_config_cmd_data_fifo.update(   config_cmd_fifo_get,
1973                                     config_cmd_fifo_put,
[585]1974                                     r_config_cmd_wdata.read() );
[434]1975    m_config_cmd_be_fifo.update(     config_cmd_fifo_get,
1976                                     config_cmd_fifo_put,
[585]1977                                     r_config_cmd_be.read() );
[434]1978    m_config_cmd_eop_fifo.update(    config_cmd_fifo_get,
1979                                     config_cmd_fifo_put,
[585]1980                                     r_config_cmd_eop.read() );
[240]1981   
[434]1982    //////////////////////////////////////////////////////////////////////////
1983    // CONFIG_RSP fifo update
1984    // There is two writers : CONFIG_CMD FSM & CONFIG_RSP FSM
1985    //////////////////////////////////////////////////////////////////////////
1986
1987    if ( r_alloc_fifo_config_rsp_local.read() )  // owner is CONFIG_CMD FSM
1988                                                 // response for a local config transaction
[240]1989    {
[434]1990        m_config_rsp_data_fifo.update(   config_rsp_fifo_get,
1991                                         config_rsp_fifo_put,
[585]1992                                         r_config_cmd_rdata.read() ); 
[434]1993        m_config_rsp_rsrcid_fifo.update( config_rsp_fifo_get,
1994                                         config_rsp_fifo_put,
1995                                         p_vci_tgt_int.srcid.read() );
1996        m_config_rsp_rtrdid_fifo.update( config_rsp_fifo_get,
1997                                         config_rsp_fifo_put,
1998                                         p_vci_tgt_int.trdid.read() );
1999        m_config_rsp_rpktid_fifo.update( config_rsp_fifo_get,
2000                                         config_rsp_fifo_put,
2001                                         p_vci_tgt_int.pktid.read() );
2002        m_config_rsp_reop_fifo.update(   config_rsp_fifo_get,
2003                                         config_rsp_fifo_put,
2004                                         true );                // local config are one flit
2005        m_config_rsp_rerror_fifo.update( config_rsp_fifo_get,
2006                                         config_rsp_fifo_put,
2007                                         r_config_cmd_error.read() );
[240]2008    }
[434]2009    else                                         // owner is CONFIG_RSP FSM
2010                                                 // response for a remote transaction
2011    {
[585]2012        // PUT  depends on CONFIG_RSP FSM state
2013        uint32_t rdata;
2014        bool     reop;
2015        if ( r_config_rsp_fsm.read() == CONFIG_RSP_PUT_HI )
2016        {
2017            config_rsp_fifo_put = true;
2018            rdata               = (uint32_t)(p_vci_ini_iox.rdata.read()>>32);
2019            reop                = p_vci_ini_iox.reop.read(); 
2020        }
2021        else if ( r_config_rsp_fsm.read() == CONFIG_RSP_PUT_LO )
2022        {
2023            config_rsp_fifo_put = true;
2024            rdata               = (uint32_t)(p_vci_ini_iox.rdata.read());
2025            reop                = false;
2026        }
2027        else if ( r_config_rsp_fsm.read() == CONFIG_RSP_PUT_UNC )
2028        {
2029            config_rsp_fifo_put = true;
2030            rdata               = (uint32_t)(p_vci_ini_iox.rdata.read());
2031            reop                = true;
2032        }
2033        else
2034        {
2035            config_rsp_fifo_put = false;
2036            rdata               = 0;
2037            reop                = false;;
2038        }
2039
[434]2040        m_config_rsp_data_fifo.update(   config_rsp_fifo_get,
2041                                         config_rsp_fifo_put,
[585]2042                                         rdata );
[434]2043        m_config_rsp_rsrcid_fifo.update( config_rsp_fifo_get,
2044                                         config_rsp_fifo_put,
2045                                         p_vci_ini_iox.rsrcid.read() );
2046        m_config_rsp_rtrdid_fifo.update( config_rsp_fifo_get,
2047                                         config_rsp_fifo_put,
2048                                         p_vci_ini_iox.rtrdid.read() );
2049        m_config_rsp_rpktid_fifo.update( config_rsp_fifo_get,
2050                                         config_rsp_fifo_put,
2051                                         p_vci_ini_iox.rpktid.read() );
2052        m_config_rsp_reop_fifo.update(   config_rsp_fifo_get,
2053                                         config_rsp_fifo_put,
[585]2054                                         reop );
[434]2055        m_config_rsp_rerror_fifo.update( config_rsp_fifo_get,
2056                                         config_rsp_fifo_put,
2057                                         p_vci_ini_iox.rerror.read() );
2058    }
2059   
[240]2060} // end transition()
2061
2062///////////////////////
2063tmpl(void)::genMoore()
2064///////////////////////
2065{
[434]2066    // VCI initiator command on RAM network
2067    // directly the content of the dma_cmd FIFO
2068
2069    p_vci_ini_ram.cmdval  = m_dma_cmd_addr_fifo.rok(); 
2070    p_vci_ini_ram.address = m_dma_cmd_addr_fifo.read();
2071    p_vci_ini_ram.be      = m_dma_cmd_be_fifo.read();
2072    p_vci_ini_ram.cmd     = m_dma_cmd_cmd_fifo.read();
2073    p_vci_ini_ram.contig  = m_dma_cmd_contig_fifo.read();
2074    p_vci_ini_ram.wdata   = m_dma_cmd_data_fifo.read(); 
2075    p_vci_ini_ram.eop     = m_dma_cmd_eop_fifo.read();
2076    p_vci_ini_ram.cons    = m_dma_cmd_cons_fifo.read();
2077    p_vci_ini_ram.plen    = m_dma_cmd_plen_fifo.read();
2078    p_vci_ini_ram.wrap    = m_dma_cmd_wrap_fifo.read();
2079    p_vci_ini_ram.cfixed  = m_dma_cmd_cfixed_fifo.read();
2080    p_vci_ini_ram.clen    = m_dma_cmd_clen_fifo.read();
2081    p_vci_ini_ram.trdid   = m_dma_cmd_trdid_fifo.read();
2082    p_vci_ini_ram.pktid   = m_dma_cmd_pktid_fifo.read();
2083    p_vci_ini_ram.srcid   = m_dma_cmd_srcid_fifo.read();
[240]2084   
[434]2085    // VCI target command ack on IOX network
2086    // depends on the DMA_CMD FSM state
[240]2087
2088    switch ( r_dma_cmd_fsm.read() ) 
2089    {
2090    case DMA_CMD_IDLE:
[434]2091    case DMA_CMD_MISS_WAIT:
2092        p_vci_tgt_iox.cmdack  = false;
[240]2093        break;
[434]2094    case DMA_CMD_WAIT_EOP:
2095        p_vci_tgt_iox.cmdack  = true;
[240]2096        break;
[434]2097    case DMA_CMD_FIFO_PUT_CMD:
2098        p_vci_tgt_iox.cmdack  = m_dma_cmd_addr_fifo.wok();
[240]2099        break;
[434]2100    case DMA_CMD_FIFO_PUT_RSP:
2101        p_vci_tgt_iox.cmdack  = m_dma_rsp_data_fifo.wok();
[240]2102        break; 
[585]2103    }
[240]2104
[434]2105    // VCI target response on IOX network
2106    // directly the content of the DMA_RSP FIFO
[240]2107
[434]2108    p_vci_tgt_iox.rspval  = m_dma_rsp_data_fifo.rok();
2109    p_vci_tgt_iox.rsrcid  = m_dma_rsp_rsrcid_fifo.read();
2110    p_vci_tgt_iox.rtrdid  = m_dma_rsp_rtrdid_fifo.read();
2111    p_vci_tgt_iox.rpktid  = m_dma_rsp_rpktid_fifo.read();
2112    p_vci_tgt_iox.rdata   = m_dma_rsp_data_fifo.read(); 
2113    p_vci_tgt_iox.rerror  = m_dma_rsp_rerror_fifo.read();
2114    p_vci_tgt_iox.reop    = m_dma_rsp_reop_fifo.read();
[240]2115
[434]2116    // VCI initiator response on the RAM Network
2117    // depends on the DMA_RSP FSM state
[240]2118
[434]2119        p_vci_ini_ram.rspack = m_dma_rsp_data_fifo.wok() and
2120                           (r_dma_rsp_fsm.read() == DMA_RSP_FIFO_PUT) and
2121                           not r_alloc_fifo_dma_rsp_local.read();
[240]2122
[434]2123    // VCI initiator command on IOX network
2124    // directly the content of the CONFIG_CMD FIFO
2125
2126    p_vci_ini_iox.cmdval  = m_config_cmd_addr_fifo.rok();
2127    p_vci_ini_iox.address = m_config_cmd_addr_fifo.read();
2128    p_vci_ini_iox.be      = m_config_cmd_be_fifo.read();
2129    p_vci_ini_iox.cmd     = m_config_cmd_cmd_fifo.read();
2130    p_vci_ini_iox.contig  = m_config_cmd_contig_fifo.read();
[585]2131    p_vci_ini_iox.wdata   = m_config_cmd_data_fifo.read(); 
[434]2132    p_vci_ini_iox.eop     = m_config_cmd_eop_fifo.read();
2133    p_vci_ini_iox.cons    = m_config_cmd_cons_fifo.read();
2134    p_vci_ini_iox.plen    = m_config_cmd_plen_fifo.read();
2135    p_vci_ini_iox.wrap    = m_config_cmd_wrap_fifo.read();
2136    p_vci_ini_iox.cfixed  = m_config_cmd_cfixed_fifo.read();
2137    p_vci_ini_iox.clen    = m_config_cmd_clen_fifo.read();
2138    p_vci_ini_iox.trdid   = m_config_cmd_trdid_fifo.read();
2139    p_vci_ini_iox.pktid   = m_config_cmd_pktid_fifo.read();
2140    p_vci_ini_iox.srcid   = m_config_cmd_srcid_fifo.read();
[240]2141   
[434]2142    // VCI target command ack on INT network
[240]2143    // it depends on the CONFIG_CMD FSM state
2144
2145    switch ( r_config_cmd_fsm.read() ) 
2146    {
2147    case CONFIG_CMD_IDLE:
[585]2148        p_vci_tgt_int.cmdack  = true;
2149        break;
2150    case CONFIG_CMD_NEXT: 
2151        p_vci_tgt_int.cmdack  = true;
2152        break;
2153    case CONFIG_CMD_PUT:         
[434]2154        p_vci_tgt_int.cmdack  = false;
[240]2155        break;
[585]2156    case CONFIG_CMD_RSP:         
2157        p_vci_tgt_int.cmdack  = false;
[240]2158        break;
[585]2159    }
[240]2160
[434]2161    // VCI target response on INT network
2162    // directly the content of the CONFIG_RSP FIFO
[240]2163
[434]2164    p_vci_tgt_int.rspval  = m_config_rsp_data_fifo.rok();
2165        p_vci_tgt_int.rsrcid  = m_config_rsp_rsrcid_fifo.read();
2166    p_vci_tgt_int.rtrdid  = m_config_rsp_rtrdid_fifo.read();
2167    p_vci_tgt_int.rpktid  = m_config_rsp_rpktid_fifo.read();
2168    p_vci_tgt_int.rdata   = m_config_rsp_data_fifo.read();
2169    p_vci_tgt_int.rerror  = m_config_rsp_rerror_fifo.read();
2170    p_vci_tgt_int.reop    = m_config_rsp_reop_fifo.read();
[240]2171   
[434]2172    // VCI initiator response on IOX Network
[240]2173    // it depends on the CONFIG_RSP FSM state
2174
[434]2175        p_vci_ini_iox.rspack = m_config_rsp_data_fifo.wok() and
[585]2176                           not r_alloc_fifo_config_rsp_local.read() and
2177                           ( (r_config_rsp_fsm.read() == CONFIG_RSP_PUT_UNC) or
2178                             (r_config_rsp_fsm.read() == CONFIG_RSP_PUT_HI) );
[434]2179
2180    // VCI initiator command  on INT network
[549]2181    // it depends on the MISS_WTI_CMD FSM state   
2182    // - WTI : single flit WRITE
2183    // - MISS TLB : multi-flit READ for a complete cache line
[434]2184
2185    // default values
2186    p_vci_ini_int.srcid   = m_int_srcid;
2187    p_vci_ini_int.trdid   = 0;
2188    p_vci_ini_int.cfixed  = false;
2189    p_vci_ini_int.eop     = true;
2190    p_vci_ini_int.wrap    = false;
2191    p_vci_ini_int.clen    = 0;
[549]2192    p_vci_ini_int.contig  = true;
2193    p_vci_ini_int.cons    = false;
2194    p_vci_ini_int.be      = 0xF;
[240]2195   
[434]2196    switch ( r_miss_wti_cmd_fsm.read() ) 
[240]2197    {   
[434]2198    case MISS_WTI_CMD_IDLE:
2199                p_vci_ini_int.cmdval  = false;
2200        p_vci_ini_int.address = 0;
2201        p_vci_ini_int.cmd     = vci_param_int::CMD_NOP;
2202        p_vci_ini_int.pktid   = PKTID_READ;
2203        p_vci_ini_int.wdata   = 0;
2204        p_vci_ini_int.plen    = 0;
[240]2205        break;
2206   
[434]2207    case MISS_WTI_CMD_WTI:
2208        p_vci_ini_int.cmdval  = true;
2209        p_vci_ini_int.address = r_iommu_peri_wti[r_miss_wti_cmd_index.read()].read(); 
2210        p_vci_ini_int.cmd     = vci_param_int::CMD_WRITE;
2211        p_vci_ini_int.pktid   = PKTID_WRITE;
2212        p_vci_ini_int.wdata   = (int_data_t)r_irq_pending[r_miss_wti_cmd_index.read()].read();
2213        p_vci_ini_int.plen    = vci_param_int::B;
[240]2214        break;
2215   
[434]2216    case MISS_WTI_CMD_MISS:
2217        p_vci_ini_int.cmdval  = true;
2218        p_vci_ini_int.address = r_tlb_paddr.read() & CACHE_LINE_MASK;
2219        p_vci_ini_int.cmd     = vci_param_int::CMD_READ;
2220        p_vci_ini_int.pktid   = PKTID_READ;
2221        p_vci_ini_int.wdata   = 0;
2222        p_vci_ini_int.plen    = m_words*(vci_param_int::B);
[240]2223        break;
[434]2224    }
[240]2225
[434]2226    // VCI initiator response on INT network
2227    // It depends on the MISS_WTI_RSP FSM state
2228
2229    if ( r_miss_wti_rsp_fsm.read() == MISS_WTI_RSP_IDLE ) p_vci_ini_int.rspack  = false;
2230    else                                                  p_vci_ini_int.rspack  = true;
2231
[240]2232} // end genMoore
2233
2234}}
2235
2236// Local Variables:
2237// tab-width: 4
2238// c-basic-offset: 4
2239// c-file-offsets:((innamespace . 0)(inline-open . 0))
2240// indent-tabs-mode: nil
2241// End:
2242
2243// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.