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

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

Compliance with mapping_table defined in release 2462
Introducing the dspin_router_tsar component used in tsar_generic_iob
platform to implement the RAM networt (between L2 & L3).

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