/* i*- c++ -*-C * File : vci_io_bridge.cpp * Copyright (c) UPMC, Lip6, SoC * * SOCLIB_LGPL_HEADER_BEGIN * * This file is part of SoCLib, GNU LGPLv2.1. * * SoCLib is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; version 2.1 of the License. * * SoCLib is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with SoCLib; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA * * SOCLIB_LGPL_HEADER_END */ #include #include "arithmetics.h" #include "alloc_elems.h" #include "../include/vci_io_bridge.h" ////// debug services /////////////////////////////////////////////////////// // All debug messages are conditionned by two variables: // - compile time : DEBUG_*** : defined below // - execution time : m_debug_*** : defined by constructor arguments // m_debug_* = (m_debug_ok) and (m_cpt_cycle > m_debug_start_cycle) ///////////////////////////////////////////////////////////////////////////////// #define DEBUG_DMA_CMD 1 #define DEBUG_DMA_RSP 1 #define DEBUG_DMA_TLB 1 #define DEBUG_CONFIG_CMD 1 #define DEBUG_CONFIG_RSP 1 #define DEBUG_MISS_INIT 1 #define NEW_XRAM_VCI 0 #define IOMMU_ID 4097 namespace soclib { namespace caba { namespace { //DMA const char *dma_cmd_fsm_state_str[] = { "DMA_CMD_IDLE", "DMA_CMD_TRT_LOCK", "DMA_CMD_TRT_WAIT", "DMA_CMD_TRT_SET", "DMA_CMD_FIFO_PUT", "DMA_CMD_FIFO_MISS_PUT", "DMA_CMD_TLB_MISS_WAIT", "DMA_CMD_TLB_MISS_STORE", "DMA_CMD_ERROR", }; const char *dma_rsp_fsm_state_str[] = { "DMA_RSP_IDLE", "DMA_RSP_TRT_LOCK", "DMA_RSP_FIFO_PUT", "DMA_RSP_FIFO_ERROR_PUT", }; const char *alloc_trt_dma_fsm_state_str[] = { "ALLOC_TRT_DMA_CMD", "ALLOC_TRT_DMA_RSP", }; const char *dma_tlb_fsm_state_str[] = { "DMA_TLB_IDLE", "DMA_TLB_MISS", "DMA_TLB_PTE1_GET", "DMA_TLB_PTE1_SELECT", "DMA_TLB_PTE1_UPDT", "DMA_TLB_PTE2_GET", "DMA_TLB_PTE2_SELECT", "DMA_TLB_PTE2_UPDT", "DMA_TLB_WAIT_TRANSACTION", "DMA_TLB_RETURN", "DMA_TLB_INVAL_CHECK", "DMA_TLB_INVAL_SCAN", }; //CONFIG const char *config_cmd_fsm_state_str[] = { "CONFIG_CMD_IDLE", "CONFIG_CMD_TRT_LOCK", "CONFIG_CMD_TRT_WAIT", "CONFIG_CMD_TRT_SET", "CONFIG_CMD_FIFO_PUT", // IOB private configuration segment "CONFIG_CMD_PTPR_WRITE", "CONFIG_CMD_PTPR_READ", "CONFIG_CMD_ACTIVE_WRITE", "CONFIG_CMD_ACTIVE_READ", "CONFIG_CMD_BVAR_READ", "CONFIG_CMD_ETR_READ", "CONFIG_CMD_BAD_ID_READ", "CONFIG_CMD_INVAL_REQ", "CONFIG_CMD_INVAL", "CONFIG_CMD_IT_ADDR_IOMMU_WRITE_1", "CONFIG_CMD_IT_ADDR_IOMMU_WRITE_2", "CONFIG_CMD_IT_ADDR_IOMMU_READ_1", "CONFIG_CMD_IT_ADDR_IOMMU_READ_2", "CONFIG_CMD_IT_ADDR_WRITE_1", "CONFIG_CMD_IT_ADDR_WRITE_2", "CONFIG_CMD_IT_ADDR_READ_1", "CONFIG_CMD_IT_ADDR_READ_2", "CONFIG_CMD_ERROR_WAIT", "CONFIG_CMD_ERROR_RSP", }; const char *config_rsp_fsm_state_str[] = { "CONFIG_RSP_IDLE", "CONFIG_RSP_TRT_LOCK", "CONFIG_RSP_FIFO_PUT", }; const char *alloc_trt_config_fsm_state_str[] = { "ALLOC_TRT_CONFIG_CMD", "ALLOC_TRT_CONFIG_RSP", }; //MISS TRANSACTIONS (to Direct Network) const char *miss_init_fsm_state_str[] = { "MISS_INIT_IDLE_MISS", "MISS_INIT_IDLE_IRQ", "MISS_INIT_IRQ_CMD", "MISS_INIT_IRQ_RSP", "MISS_INIT_TLB_MISS_CMD", "MISS_INIT_TLB_MISS_RSP", }; } #define tmpl(...) template __VA_ARGS__ VciIoBridge ///////////////////////////////// tmpl(/**/)::VciIoBridge( sc_module_name name, size_t nb_periph, const soclib::common::MappingTable &mtx, const soclib::common::MappingTable &mtd, const soclib::common::MappingTable &mtio, const soclib::common::Segment &seg_config_iob, const soclib::common::IntTab &tgt_index_iocluster, // const soclib::common::IntTab &tgt_index_config, const soclib::common::IntTab &init_index_direct, const soclib::common::IntTab &tgt_index_iospace, const soclib::common::IntTab &init_index_iospace, const soclib::common::IntTab &init_index_dma, size_t dcache_words, size_t iotlb_ways, size_t iotlb_sets, uint32_t debug_start_cycle, bool debug_ok) : soclib::caba::BaseModule(name), p_clk("clk"), p_resetn("resetn"), p_irq_in(soclib::common::alloc_elems >("irq_in", nb_periph)), p_vci_ini_dma("vci_ini_dma"), p_vci_tgt_dma("vci_tgt_dma"), p_vci_ini_config("vci_ini_config"), p_vci_tgt_config("vci_tgt_config"), p_vci_ini_miss("vci_ini_miss"), m_words(dcache_words), m_nb_periph(nb_periph), // m_locality_table_config(mtd.getLocalityTable(tgt_index_iocluster)), // These structures simulate what in hardware will be a correspondence table // Between segments' base address on the direct space and on the IO space // m_routing_table_config(mtd.getRoutingTable(tgt_index_iocluster)), //m_mtio(mtio), m_transaction_tab_dma(2), m_transaction_tab_config(1), //Direct Network // m_segment_config(mtd.getSegment(tgt_index_config)), m_segment_config(seg_config_iob), m_srcid_miss(mtx.indexForId(init_index_direct)), //XRAM Network m_srcid_dma(mtx.indexForId(init_index_dma)), //IO Network m_segment_io(mtio.getSegment(tgt_index_iospace)), m_srcid_config(mtio.indexForId(init_index_iospace)), m_iotlb_ways(iotlb_ways), m_iotlb_sets(iotlb_sets), m_paddr_nbits(vci_param_d::N), m_debug_start_cycle(debug_start_cycle), m_debug_ok(debug_ok), r_iommu_ptpr("r_iommu_ptpr"), r_iommu_active("r_iommu_active"), r_iommu_bvar("r_iommu_bvar"), r_iommu_etr("r_iommu_etr"), r_iommu_bad_id("r_iommu_bad_id"), r_it_addr_iommu("r_it_addr_iommu"), // DMA_CMD r_dma_cmd_fsm("r_dma_cmd_fsm"), r_dma_cmd_fsm_save("r_dma_cmd_fsm_save"), r_miss_interrupt("r_miss_interrupt"), r_dma_cmd_count("r_dma_cmd_count"), r_dma_cmd_trt_index("r_dma_cmd_trt_index"), r_dma_paddr("r_dma_paddr"), // FIFOs m_dma_cmd_addr_fifo("m_dma_cmd_addr_fifo",4), //m_dma_cmd_length_fifo("m_dma_cmd_length_fifo",4), m_dma_cmd_srcid_fifo("m_dma_cmd_srcid_fifo",4), m_dma_cmd_trdid_fifo("m_dma_cmd_trdid_fifo",4), m_dma_cmd_pktid_fifo("m_dma_cmd_pktid_fifo",4), m_dma_cmd_be_fifo("m_dma_cmd_be_fifo",4), m_dma_cmd_cmd_fifo("m_dma_cmd_cmd_fifo",4), m_dma_cmd_contig_fifo("m_dma_cmd_contig_fifo",4), m_dma_cmd_data_fifo("m_dma_cmd_data_fifo",4), m_dma_cmd_eop_fifo("m_dma_cmd_eop_fifo",4), m_dma_cmd_cons_fifo("m_dma_cmd_cons_fifo",4), m_dma_cmd_plen_fifo("m_dma_cmd_plen_fifo",4), m_dma_cmd_wrap_fifo("m_dma_cmd_wrap_fifo",4), m_dma_cmd_cfixed_fifo("m_dma_cmd_cfixed_fifo",4), m_dma_cmd_clen_fifo("m_dma_cmd_clen_fifo",4), r_miss_paddr ("r_miss_paddr"), r_miss_cmd ("r_miss_cmd"), r_miss_contig ("r_miss_contig"), r_miss_cons ("r_miss_cons"), r_miss_plen ("r_miss_plen"), r_miss_wrap ("r_miss_wrap"), r_miss_cfixed ("r_miss_cfixed"), r_miss_clen ("r_miss_clen"), r_miss_srcid ("r_miss_srcid"), r_miss_trdid ("r_miss_trdid"), r_miss_pktid ("r_miss_pktid"), r_dma_error_type("r_dma_error_type"), r_dma_error_trdid("r_dma_error_trdid"), r_dma_error_pktid("r_dma_error_pktid"), r_dma_tlb_fsm("r_dma_tlb_fsm"), r_waiting_transaction("r_waiting_transaction"), r_tlb_miss_type("r_tlb_miss_type"), r_iotlb_vaddr("r_iotlb_vaddr"), // virtual address for a tlb miss r_iotlb_paddr("r_iotlb_paddr"), // physical address of pte r_iotlb_pte_flags("r_iotlb_pte_flags"),// pte1 or first word of pte2 r_iotlb_pte_ppn("r_iotlb_pte_ppn"), // second word of pte2 r_iotlb_way("r_iotlb_way"), // selected way in tlb r_iotlb_set("r_iotlb_set"), // selected set in tlb r_iotlb("iotlb", IOMMU_ID, iotlb_ways,iotlb_sets,vci_param_d::N), //DMA_RSP r_dma_rsp_fsm("r_dma_rsp_fsm"), r_dma_rtrdid("r_dma_rtrdid"), r_dma_rsrcid("r_dma_rsrcid"), //Fifo's m_dma_rsp_data_fifo("m_dma_rsp_data_fifo",4), m_dma_rsp_rsrcid_fifo("m_dma_rsp_rsrcid_fifo",4), m_dma_rsp_rtrdid_fifo("m_dma_rsp_rtrdid_fifo",4), m_dma_rsp_rpktid_fifo("m_dma_rsp_rpktid_fifo",4), m_dma_rsp_reop_fifo("m_dma_rsp_reop_fifo",4), m_dma_rsp_rerror_fifo("m_dma_rsp_rerror_fifo",4), r_dma_cmd_rsp_erase_req("r_dma_cmd_rsp_erase_req"), r_dma_cmd_error_req("r_dma_cmd_error_req"), r_dma_tlb_req("r_dma_tlb_req"), r_tlb_dma_untreated("r_tlb_dma_untreated"), r_dma_tlb_error_req("r_dma_tlb_error_req"), r_config_tlb_req("r_config_tlb_req"), r_config_tlb_inval_vaddr("r_config_tlb_inval_vaddr"), // ALLOC TRT DMA r_alloc_trt_dma_fsm("r_alloc_trt_dma_fsm"), // CONFIG CMD r_config_cmd_fsm("r_config_cmd_fsm"), r_config_cmd_trt_index("r_config_cmd_trt_index"), m_config_cmd_addr_fifo("m_config_cmd_addr_fifo",4), //m_config_cmd_length_fifo("m_config_cmd_length_fifo",4), m_config_cmd_srcid_fifo("m_config_cmd_srcid_fifo",4), m_config_cmd_trdid_fifo("m_config_cmd_trdid_fifo",4), m_config_cmd_pktid_fifo("m_config_cmd_pktid_fifo",4), m_config_cmd_be_fifo("m_config_cmd_be_fifo",4), m_config_cmd_cmd_fifo("m_config_cmd_cmd_fifo",4), m_config_cmd_contig_fifo("m_config_cmd_contig_fifo",4), m_config_cmd_data_fifo("m_config_cmd_data_fifo",4), m_config_cmd_eop_fifo("m_config_cmd_eop_fifo",4), m_config_cmd_cons_fifo("m_config_cmd_cons_fifo",4), m_config_cmd_plen_fifo("m_config_cmd_plen_fifo",4), m_config_cmd_wrap_fifo("m_config_cmd_wrap_fifo",4), m_config_cmd_cfixed_fifo("m_config_cmd_cfixed_fifo",4), m_config_cmd_clen_fifo("m_config_cmd_clen_fifo",4), // Private configuration registers r_config_error_type("r_config_error_type"), r_config_first_word("r_config_first_word"), r_it_index("r_it_index"), //Fifo's m_config_local_data_fifo("m_config_local_data_fifo",4), m_config_local_rsrcid_fifo("m_config_local_rsrcid_fifo",4), m_config_local_rtrdid_fifo("m_config_local_rtrdid_fifo",4), m_config_local_rpktid_fifo("m_config_local_rpktid_fifo",4), m_config_local_reop_fifo("m_config_local_reop_fifo",4), m_config_local_rerror_fifo("m_config_local_rerror_fifo",4), r_config_vaddr("r_config_vaddr"), // CONFIG RSP r_config_rsp_fsm("r_config_rsp_fsm"), r_config_rtrdid("r_config_rtrdid"), r_config_rsrcid("r_config_rsrcid"), //Fifo's m_config_rsp_data_fifo("m_config_rsp_data_fifo",4), m_config_rsp_rsrcid_fifo("m_config_rsp_rsrcid_fifo",4), m_config_rsp_rtrdid_fifo("m_config_rsp_rtrdid_fifo",4), m_config_rsp_rpktid_fifo("m_config_rsp_rpktid_fifo",4), m_config_rsp_reop_fifo("m_config_rsp_reop_fifo",4), m_config_rsp_rerror_fifo("m_config_rsp_rerror_fifo",4), // Communication between CONFIG CMD and CONFIG RSP r_config_cmd_rsp_erase_req("r_config_cmd_rsp_erase_req"), // ALLOC TRT CONFIG r_alloc_trt_config_fsm("r_alloc_trt_config_fsm"), // MISS INIT r_miss_init_fsm("r_miss_init_fsm"), r_miss_rdata("r_miss_rdata"), r_miss_rpktid("r_miss_rpktid"), r_miss_rtrdid("r_miss_rtrdid"), r_miss_rerror("r_miss_rerror"), r_miss_reop("r_miss_reop"), //r_miss_rsrcid("r_miss_rsrcid"), r_miss_rsp_cpt("r_miss_rsp_cpt"), //IRQ r_irq_pending("r_irq_pending"), r_irq_mask("r_irq_mask"), r_irq_chosen("r_irq_chosen"), r_tlb_miss_init_req("r_tlb_miss_init_req"), r_miss_init_error("r_miss_init_error"), r_miss_buf_valid("r_miss_buf_valid"), r_miss_buf_tag("r_miss_buf_tag") { assert( (vci_param_d::N <= 64) and "ADDRESS cannot be bigger than 64 bits"); assert( (vci_param_x::B)*8 == 64 and (vci_param_io::B)*8 == 64 and "DATA field must be 64 bits in Extern and IO Network"); assert ( (vci_param_d::B)*8 == 32 and "Error: data field in Direct Noc must be 32 bits" ); // Interruption Address vector, one entry for each IO r_it_addr = new paddr_t[nb_periph]; // One cache line buffer r_miss_buf_data = new vci_data_t[dcache_words]; // Command storage in case of miss TLB // (dcache_words/2) => Maximal size of a write command r_miss_data = new vci_data_t[dcache_words]; r_miss_be = new vci_be_t[dcache_words]; SC_METHOD(transition); dont_initialize(); sensitive << p_clk.pos(); SC_METHOD(genMoore); dont_initialize(); sensitive << p_clk.neg(); } ///////////////////////////////////// tmpl(/**/)::~VciIoBridge() ///////////////////////////////////// { delete [] r_it_addr; delete [] r_miss_buf_data; delete [] r_miss_data; delete [] r_miss_be; soclib::common::dealloc_elems(p_irq_in, m_nb_periph); } //////////////////////////////////// tmpl(void)::print_trace(size_t mode) //////////////////////////////////// { // b0 : IOtlb trace std::cout << std::dec << "IO_BRIDGE " << name() << std::endl; std::cout << " " << dma_cmd_fsm_state_str[r_dma_cmd_fsm.read()] << " | " << dma_rsp_fsm_state_str[r_dma_rsp_fsm.read()] << " | " << dma_tlb_fsm_state_str[r_dma_tlb_fsm.read()] << " | " << alloc_trt_dma_fsm_state_str[r_alloc_trt_dma_fsm.read()] << " | " << config_cmd_fsm_state_str[r_config_cmd_fsm.read()] << " | " << config_rsp_fsm_state_str[r_config_rsp_fsm.read()] << " | " << alloc_trt_config_fsm_state_str[r_alloc_trt_config_fsm.read()] << " | " << miss_init_fsm_state_str[r_miss_init_fsm.read()]; std::cout << std::endl; if(mode & 0x01) { std::cout << " IOTLB" << std::endl; r_iotlb.printTrace(); } if(mode & 0x02) { } } //////////////////////// tmpl(void)::print_stats() //////////////////////// { std::cout << name() << std::endl << "- IOTLB MISS RATE = " << (float)m_cpt_iotlb_miss/m_cpt_iotlb_read << std::endl << "- IOTLB MISS COST = " << (float)m_cost_iotlb_miss/m_cpt_iotlb_miss << std::endl << "- IOTLB MISS TRANSACTION COST = " << (float)m_cost_iotlbmiss_transaction/m_cpt_iotlbmiss_transaction << std::endl << "- IOTLB MISS TRANSACTION RATE (OVER ALL MISSES) = " << (float)m_cpt_iotlbmiss_transaction/m_cpt_iotlb_miss << std::endl; } //////////////////////// tmpl(void)::clear_stats() //////////////////////// { m_cpt_iotlb_read = 0; m_cpt_iotlb_miss = 0; m_cost_iotlb_miss = 0; m_cpt_iotlbmiss_transaction = 0; m_cost_iotlbmiss_transaction = 0; m_cpt_trt_dma_full = 0; m_cpt_trt_dma_full_cost = 0; m_cpt_trt_config_full = 0; m_cpt_trt_config_full_cost = 0; } ///////////////////////// tmpl(void)::transition() ///////////////////////// { if ( not p_resetn.read() ) { r_dma_cmd_fsm = DMA_CMD_IDLE; r_dma_rsp_fsm = DMA_RSP_IDLE; r_alloc_trt_dma_fsm = ALLOC_TRT_DMA_CMD; r_dma_tlb_fsm = DMA_TLB_IDLE; r_config_cmd_fsm = CONFIG_CMD_IDLE; r_config_rsp_fsm = CONFIG_RSP_IDLE; r_alloc_trt_config_fsm = ALLOC_TRT_CONFIG_CMD; r_miss_init_fsm = MISS_INIT_IDLE_MISS; //miss buffer invalidation r_miss_buf_valid = false; r_iommu_active = false; r_dma_cmd_count = 0; // initializing FIFOs m_dma_cmd_addr_fifo.init(); m_dma_cmd_srcid_fifo.init(); m_dma_cmd_trdid_fifo.init(); m_dma_cmd_pktid_fifo.init(); m_dma_cmd_be_fifo.init(); m_dma_cmd_cmd_fifo.init(); m_dma_cmd_contig_fifo.init(); m_dma_cmd_data_fifo.init(); m_dma_cmd_eop_fifo.init(); m_dma_cmd_cons_fifo.init(); m_dma_cmd_plen_fifo.init(); m_dma_cmd_wrap_fifo.init(); m_dma_cmd_cfixed_fifo.init(); m_dma_cmd_clen_fifo.init(); m_dma_rsp_rsrcid_fifo.init(); m_dma_rsp_rtrdid_fifo.init(); m_dma_rsp_rpktid_fifo.init(); m_dma_rsp_data_fifo.init(); m_dma_rsp_rerror_fifo.init(); m_dma_rsp_reop_fifo.init(); m_config_cmd_addr_fifo.init(); m_config_cmd_srcid_fifo.init(); m_config_cmd_trdid_fifo.init(); m_config_cmd_pktid_fifo.init(); m_config_cmd_be_fifo.init(); m_config_cmd_cmd_fifo.init(); m_config_cmd_contig_fifo.init(); m_config_cmd_data_fifo.init(); m_config_cmd_eop_fifo.init(); m_config_cmd_cons_fifo.init(); m_config_cmd_plen_fifo.init(); m_config_cmd_wrap_fifo.init(); m_config_cmd_cfixed_fifo.init(); m_config_cmd_clen_fifo.init(); m_config_rsp_rsrcid_fifo.init(); m_config_rsp_rtrdid_fifo.init(); m_config_rsp_rpktid_fifo.init(); m_config_rsp_data_fifo.init(); m_config_rsp_rerror_fifo.init(); m_config_rsp_reop_fifo.init(); m_config_local_rsrcid_fifo.init(); m_config_local_rtrdid_fifo.init(); m_config_local_rpktid_fifo.init(); m_config_local_data_fifo.init(); m_config_local_rerror_fifo.init(); m_config_local_reop_fifo.init(); //Communication between DMA_CMD and DMA_RSP r_dma_cmd_rsp_erase_req =false; r_dma_cmd_error_req =false; //Communication between DMA_CMD and TLB r_dma_tlb_req =false; r_tlb_dma_untreated =false; //Communication betweeen TLB and CONFIG_CMD r_config_tlb_req =false; r_config_tlb_inval_vaddr =false; r_dma_tlb_error_req =false; r_tlb_error_type =false; //Communication between CONFIG_CMD and CONFIG_RSP r_config_cmd_rsp_erase_req =false; //Communication between TLB_MISS and MISS_INIT r_tlb_miss_init_req =false; r_miss_init_error =false; // Debug variables m_debug_dma_rsp_fsm = false; m_debug_dma_cmd_fsm = false; m_debug_dma_tlb_fsm = false; m_debug_config_cmd_fsm = false; m_debug_config_rsp_fsm = false; m_debug_miss_init_fsm = false; r_irq_mask = 0xFFFFFFFF; r_irq_chosen = 0; // activity counters m_cpt_total_cycles = 0; m_cpt_iotlb_read = 0; m_cpt_iotlb_miss = 0; m_cpt_iotlbmiss_transaction = 0; m_cost_iotlbmiss_transaction = 0; m_cpt_trt_dma_full = 0; m_cpt_trt_dma_full_cost = 0; m_cpt_trt_config_full = 0; m_cpt_trt_config_full_cost = 0; for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_dma_cmd [i] = 0; for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_dma_rsp [i] = 0; for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_dma_tlb [i] = 0; for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_alloc_trt_dma [i] = 0; for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_config_cmd [i] = 0; for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_config_rsp [i] = 0; for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_alloc_trt_config [i] = 0; for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_miss_init [i] = 0; return; } //bool miss_unposted = false; bool dma_cmd_fifo_put = false; bool dma_cmd_fifo_get = false; bool dma_rsp_fifo_put = false; bool dma_rsp_fifo_get = false; bool config_cmd_fifo_put = false; bool config_cmd_fifo_get = false; bool config_rsp_fifo_put = false; bool config_rsp_fifo_get = false; bool config_local_fifo_put = false; bool config_local_fifo_get = false; #ifdef INSTRUMENTATION m_cpt_fsm_dma_cmd [r_dma_cmd_fsm.read()] ++; m_cpt_fsm_dma_rsp [r_dma_rsp_fsm.read() ] ++; m_cpt_fsm_dma_tlb [r_dma_tlb_fsm.read() ] ++; m_cpt_fsm_alloc_trt_dma [r_alloc_trt_dma_fsm.read() ] ++; m_cpt_fsm_config_cmd [r_config_cmd_fsm.read() ] ++; m_cpt_fsm_config_rsp [r_config_rsp_fsm.read() ] ++; m_cpt_fsm_alloc_trt_config [r_alloc_trt_config_fsm.read() ] ++; m_cpt_fsm_miss_init [r_miss_init_fsm.read() ] ++; #endif m_cpt_total_cycles++; m_debug_dma_cmd_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok; m_debug_dma_rsp_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok; m_debug_dma_tlb_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok; m_debug_config_cmd_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok; m_debug_config_rsp_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok; m_debug_miss_init_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok; ///////////////////////////////////////////////////////////////////// // The DMA_CMD_FSM controls the following ressources: // - r_dma_cmd_fsm // - r_dma_srcid // - r_dma_tlb_req (set) // - r_tlb_dma_untreated (reset) // - r_dma_cmd_rsp_erase_req (set) /////////////////////////////////////////////////////////////////////////////// switch( r_dma_cmd_fsm.read() ) { ////////////// case DMA_CMD_IDLE: { // Treats an eventual request from TLB_MISS fsm // to send a command whose miss treatment is now finished if ( r_tlb_dma_untreated.read() ) { r_dma_cmd_fsm = DMA_CMD_TRT_LOCK;//before posting we must update TRT r_dma_cmd_fsm_save = DMA_CMD_IDLE; r_miss_interrupt = true; break; } // Error during miss treatment else if (r_dma_tlb_error_req.read()) { r_iommu_etr = r_tlb_error_type.read(); r_iommu_bvar = r_iotlb_vaddr.read(); r_iommu_bad_id = r_miss_srcid.read(); // For DMA_RSP FSM if(r_miss_cmd.read() == vci_param_io::CMD_WRITE) r_dma_error_type = WRITE_ERROR; else r_dma_error_type = READ_ERROR; r_dma_error_trdid = r_miss_trdid.read(); r_dma_error_pktid = r_miss_pktid.read(); r_dma_tlb_error_req = false; r_dma_cmd_fsm = DMA_CMD_ERROR; } if ( p_vci_tgt_dma.cmdval.read() ) { if ( not r_iommu_active.read()) // iotlb not activated { // physical address r_dma_paddr = (paddr_t)p_vci_tgt_dma.address.read(); r_dma_cmd_fsm = DMA_CMD_TRT_LOCK; } else if (r_dma_tlb_fsm.read() == DMA_TLB_IDLE || r_dma_tlb_fsm.read() == DMA_TLB_WAIT_TRANSACTION ) // iotlb activated { paddr_t paddr; // We compute physical address and check access rights : // - If MMU not activated :the physical address is equal to the virtual //address (identity mapping) and there is no access rights checking // - If MMU activated : cacheability is defined by the C bit in the PTE, // the physical address is obtained from the TLB, and the access rights are // defined by the W bit in the PTE. paddr_t iotlb_paddr; pte_info_t iotlb_flags; size_t iotlb_way; size_t iotlb_set; paddr_t iotlb_nline; bool iotlb_hit = false;; #ifdef INSTRUMENTATION m_cpt_iotlb_read++; #endif iotlb_hit = r_iotlb.translate(p_vci_tgt_dma.address.read(), &iotlb_paddr, &iotlb_flags, &iotlb_nline,// unused &iotlb_way, // unused &iotlb_set );// unused if ( iotlb_hit ) // tlb hit { paddr = iotlb_paddr; // access rights checking if ( not iotlb_flags.w and (p_vci_tgt_dma.cmd.read() == vci_param_io::CMD_WRITE) ) { r_iommu_etr = MMU_WRITE_ACCES_VIOLATION; r_iommu_bvar = p_vci_tgt_dma.address.read(); r_iommu_bad_id = p_vci_tgt_dma.srcid.read(); r_dma_cmd_fsm = DMA_CMD_ERROR; // For DMA_RSP r_dma_error_type = WRITE_ERROR; r_dma_error_trdid = p_vci_tgt_dma.trdid.read(); r_dma_error_pktid = p_vci_tgt_dma.pktid.read(); #if DEBUG_DMA_CMD if( m_debug_dma_cmd_fsm ) { std::cout << " HIT in iotlb, but writable violation" << std::endl; } #endif break; } // Physical address registration r_dma_paddr = paddr; r_dma_cmd_fsm = DMA_CMD_TRT_LOCK; } // TLB miss: we enter TLB_MISS treatment sub-fsm else { #ifdef INSTRUMENTATION m_cpt_iotlb_miss++; #endif if( r_dma_tlb_req.read() || r_tlb_dma_untreated.read() || r_dma_tlb_error_req.read() ) { // There's already a ongoing request // or a completed request but not yet put on FIFO. // We stay blocked r_dma_cmd_fsm = DMA_CMD_TLB_MISS_WAIT; #if DEBUG_DMA_CMD if( m_debug_dma_cmd_fsm ) { std::cout << " MISS in iotlb. There is a pending request." << std::endl; } #endif } else { // We register request virtual address, to be used by DMA_TLB_MISS FSM r_iotlb_vaddr = p_vci_tgt_dma.address.read(); assert((r_dma_cmd_count.read() == 0) and "ERROR: TRT counter should be 0"); r_dma_tlb_req = true; r_dma_cmd_fsm = DMA_CMD_TLB_MISS_STORE; #if DEBUG_DMA_CMD if( m_debug_dma_cmd_fsm ) { std::cout << " MISS in iotlb. No pending request." << std::endl; } #endif } } // end !hit } // end if tlb_activated } // end if cmdval break; } ///////////////////////// case DMA_CMD_TRT_LOCK: // Waiting for the lock to modify Transaction Table { if ( r_alloc_trt_dma_fsm.read() == ALLOC_TRT_DMA_CMD ) { #if DEBUG_DMA_CMD if( m_debug_dma_cmd_fsm ) { std::cout << " Check the TRT" << std::endl; } #endif size_t wok_index = 0; bool wok = !m_transaction_tab_dma.full(wok_index); if ( wok ) // TRT isn't full. Write the new transaction. { r_dma_cmd_trt_index = (vci_trdid_t)wok_index; r_dma_cmd_fsm = DMA_CMD_TRT_SET; } else // wait an empty entry in TRT { r_dma_cmd_rsp_erase_req = true; r_dma_cmd_fsm = DMA_CMD_TRT_WAIT; #if DEBUG_DMA_CMD if( m_debug_dma_cmd_fsm ) { std::cout << " TRT is full. Going to TRT_WAIT state" << std::endl; } #endif #ifdef INSTRUMENTATION m_cpt_trt_dma_full++; #endif } } break; } //////////////// case DMA_CMD_TRT_WAIT: // release the lock protecting the transaction tab // waits that RSP erases an entry { #ifdef INSTRUMENTATION m_cpt_trt_dma_full_cost++; #endif // DMA_RSP will notify an erase action by reseting this register if(!r_dma_cmd_rsp_erase_req.read()) { r_dma_cmd_fsm = DMA_CMD_TRT_LOCK; // take the lock again } break; } //////////////////////// case DMA_CMD_TRT_SET: // register a new transaction in TRT { if ( r_alloc_trt_dma_fsm.read() == ALLOC_TRT_DMA_CMD ) { if(r_miss_interrupt.read()) { m_transaction_tab_dma.set(r_dma_cmd_trt_index.read(), r_miss_srcid.read(), r_miss_trdid.read() ); r_dma_cmd_fsm = DMA_CMD_FIFO_MISS_PUT; } else { m_transaction_tab_dma.set(r_dma_cmd_trt_index.read(), p_vci_tgt_dma.srcid.read(), p_vci_tgt_dma.trdid.read() ); r_dma_cmd_fsm = DMA_CMD_FIFO_PUT; } #if DEBUG_DMA_CMD if( m_debug_dma_cmd_fsm ) { std::cout << " Set a new entry in TRT" << std::endl; if(r_miss_interrupt.read()) std::cout << " From the Network " << std::endl; else std::cout << " From miss interruption" << std::endl; } #endif } break; } /////////////////////// case DMA_CMD_FIFO_PUT: { if ( p_vci_tgt_dma.cmdval && m_dma_cmd_addr_fifo.wok() ) { dma_cmd_fifo_put = true; //miss_unposted = false; if( p_vci_tgt_dma.contig ) r_dma_paddr = r_dma_paddr.read() + 4; if( p_vci_tgt_dma.eop ) r_dma_cmd_fsm = DMA_CMD_IDLE; #if DEBUG_DMA_CMD if( m_debug_dma_cmd_fsm ) { std::cout << " Push into cmd_fifo:" << " address = " << std::hex << r_dma_paddr.read() << " srcid = " << std::dec << m_srcid_dma << " trdid = " << r_dma_cmd_trt_index.read() << " wdata = " << std::hex << p_vci_tgt_dma.wdata.read() << " be = " << p_vci_tgt_dma.be.read() << " contig = " << p_vci_tgt_dma.contig.read() << " eop = " << std::dec << p_vci_tgt_dma.eop.read() << " plen = " << std::dec << p_vci_tgt_dma.plen.read() << std::endl; } #endif } break; } /////////////////////// case DMA_CMD_FIFO_MISS_PUT: { if ( m_dma_cmd_addr_fifo.wok() ) { dma_cmd_fifo_put = true; //miss_unposted = true; if( r_miss_contig.read() ) r_miss_paddr = r_miss_paddr.read() + 4; if( r_dma_cmd_count.read() == 1 ) { r_tlb_dma_untreated = false; r_miss_interrupt = false; r_dma_cmd_fsm = r_dma_cmd_fsm_save.read(); } r_dma_cmd_count = r_dma_cmd_count.read() - 1; #if DEBUG_DMA_CMD if( m_debug_dma_cmd_fsm ) { std::cout << " Push into cmd_fifo:" << " counter = " << std::hex << r_dma_cmd_count.read() << " address = " << std::hex << r_miss_paddr.read() << " srcid = " << std::dec << r_miss_srcid.read() << " trdid = " << r_miss_trdid.read() << " wdata = " << std::hex << r_miss_data << " be = " << r_miss_be << " plen = " << std::dec << r_miss_plen.read() << std::endl; } #endif } break; } /////////////////// case DMA_CMD_TLB_MISS_WAIT: // to store the miss request there must be // neither an ongoing request, nor a unposted finished request { // Treats an eventual request from TLB_MISS fsm // to send a command whose miss treatment is now finished if ( r_tlb_dma_untreated.read() ) { r_dma_cmd_fsm = DMA_CMD_TRT_LOCK; //before posting we must update TRT r_dma_cmd_fsm_save = DMA_CMD_TLB_MISS_WAIT; r_miss_interrupt = true; break; } // Error during miss treatment else if (r_dma_tlb_error_req.read()) { r_iommu_etr = r_tlb_error_type.read(); r_iommu_bvar = r_iotlb_vaddr.read(); r_iommu_bad_id = r_miss_srcid.read(); // For DMA_RSP FSM if(r_miss_cmd.read() == vci_param_io::CMD_WRITE) r_dma_error_type = WRITE_ERROR; else r_dma_error_type = READ_ERROR; r_dma_error_trdid = r_miss_trdid.read(); r_dma_error_pktid = r_miss_pktid.read(); r_dma_tlb_error_req = false; r_dma_cmd_fsm = DMA_CMD_ERROR; } #ifdef INSTRUMENTATION m_cost_iotlb_miss++; // Now it represents misses' total blocking cost (not the treatment cost itself) #endif else if (not r_dma_tlb_req.read()) { r_dma_cmd_fsm = DMA_CMD_TLB_MISS_STORE; assert((r_dma_cmd_count.read() == 0) and "ERROR: TRT counter should be 0"); } break; } /////////////////// case DMA_CMD_TLB_MISS_STORE: { if ( p_vci_tgt_dma.cmdval.read()) { if(r_dma_cmd_count.read() == 0) { r_miss_cmd = p_vci_tgt_dma.cmd.read(); r_miss_contig = p_vci_tgt_dma.contig.read(); r_miss_cons = p_vci_tgt_dma.cons.read(); r_miss_plen = p_vci_tgt_dma.plen.read(); r_miss_wrap = p_vci_tgt_dma.wrap.read(); r_miss_cfixed = p_vci_tgt_dma.cfixed.read(); r_miss_clen = p_vci_tgt_dma.clen.read(); r_miss_srcid = p_vci_tgt_dma.srcid.read(); r_miss_trdid = p_vci_tgt_dma.trdid.read(); r_miss_pktid = p_vci_tgt_dma.pktid.read(); // r_dma_tlb_req = true; } r_miss_data[r_dma_cmd_count.read()] = p_vci_tgt_dma.wdata.read(); r_miss_be[r_dma_cmd_count.read()] = p_vci_tgt_dma.be.read(); r_dma_cmd_count = r_dma_cmd_count.read() + 1; if( p_vci_tgt_dma.eop ) r_dma_cmd_fsm = DMA_CMD_IDLE; #if DEBUG_DMA_CMD if( m_debug_dma_cmd_fsm ) { std::cout << " Storing VCI fields of command that originate the Miss:" << " counter = " << std::hex << r_dma_cmd_count.read() << " address = " << std::hex << p_vci_tgt_dma.address.read() << " srcid = " << std::dec << p_vci_tgt_dma.srcid.read() << " trdid = " << p_vci_tgt_dma.trdid.read() << " wdata = " << std::hex << p_vci_tgt_dma.wdata.read() << " be = " << p_vci_tgt_dma.be.read() << " plen = " << std::dec << p_vci_tgt_dma.plen.read() << std::endl; } #endif } break; } /////////////////// case DMA_CMD_ERROR: { // Wait in case of pending request // it isn't the case, generally if(!r_dma_cmd_error_req.read()) { r_dma_cmd_error_req = true; r_dma_cmd_fsm = DMA_CMD_IDLE; } break; } } // end switch DMA_CMD_FSM ///////////////////////////////////////////////////////////////////// // The DMA_RSP_FSM controls the following ressources: // - r_dma_rsp_fsm // - r_dma_cmd_rsp_erase_req (reset) // - r_fma_error_req (reset) // - ////////////////////////////////////////////////////////////////////////////// switch( r_dma_rsp_fsm.read() ) { ///////////////////// case DMA_RSP_IDLE: { // Interruption from DMA_CMD following an error if(r_dma_cmd_error_req.read()) r_dma_rsp_fsm = DMA_RSP_FIFO_ERROR_PUT; if(p_vci_ini_dma.rspval.read()) { r_dma_rsp_fsm = DMA_RSP_TRT_LOCK; } break; } ///////////////////// case DMA_RSP_TRT_LOCK: { if ( r_alloc_trt_dma_fsm.read() == ALLOC_TRT_DMA_RSP ) { #if DEBUG_DMA_RSP if( m_debug_dma_rsp_fsm ) { std::cout << " Erase entry" << std::endl; } #endif uint32_t trdid_xram = p_vci_ini_dma.rtrdid.read(); r_dma_rsrcid = (vci_srcid_t)m_transaction_tab_dma.readSrcid(trdid_xram); r_dma_rtrdid = (vci_trdid_t)m_transaction_tab_dma.readTrdid(trdid_xram); m_transaction_tab_dma.erase(trdid_xram); if (r_dma_cmd_rsp_erase_req.read()) r_dma_cmd_rsp_erase_req = false; r_dma_rsp_fsm = DMA_RSP_FIFO_PUT; } break; } ////////////////// case DMA_RSP_FIFO_PUT: { if(p_vci_ini_dma.rspval.read() && m_dma_rsp_data_fifo.wok()) { dma_rsp_fifo_put = true; if(p_vci_ini_dma.reop.read()) r_dma_rsp_fsm = DMA_RSP_IDLE; #if DEBUG_DMA_RSP if( m_debug_dma_rsp_fsm ) { std::cout << " Push into rsp_fifo:" << " rsrcid = " << std::dec << r_dma_rsrcid.read() << " rtrdid = " << r_dma_rtrdid.read() << " rdata = " << std::hex << p_vci_ini_dma.rdata.read() << std::endl; } #endif } break; } ////////////////// case DMA_RSP_FIFO_ERROR_PUT: { if(m_dma_rsp_data_fifo.wok()) { dma_rsp_fifo_put = true; r_dma_rsp_fsm = DMA_RSP_IDLE; #if DEBUG_DMA_RSP if( m_debug_dma_rsp_fsm ) { std::cout << " Push into rsp_fifo:" << " rsrcid = " << std::dec << r_iommu_bad_id.read() << " rtrdid = " << r_dma_error_trdid.read() << " rerror = " << r_dma_error_type.read() << " rdata = " << std::hex << 0 << std::endl; } #endif } break; } } // end switch DMA_RSP_FSM //////////////////////////////////////////////////////////////////////////// // The ALLOC_TRT_DMA fsm allocates the access to the Transaction Table (m_transaction_tab_dma) // with a round robin priority between 2 user FSMs : // - DMA_CMD : to set a new entry // - DMA_RSP : to read and erase an entry // The ressource is always allocated. //////////////////////////////////////////////////////////////////////////// switch ( r_alloc_trt_dma_fsm.read() ) { /////////////////// case ALLOC_TRT_DMA_CMD: { if ( r_dma_cmd_fsm.read() != DMA_CMD_TRT_LOCK ) { if (r_dma_rsp_fsm.read() == DMA_RSP_TRT_LOCK) r_alloc_trt_dma_fsm = ALLOC_TRT_DMA_RSP; } break; } /////////////////// case ALLOC_TRT_DMA_RSP: { if (r_dma_rsp_fsm.read() != DMA_RSP_TRT_LOCK) { if (r_dma_cmd_fsm.read() == DMA_CMD_TRT_LOCK) r_alloc_trt_dma_fsm = ALLOC_TRT_DMA_CMD; } break; } } // end switch r_alloc_trt_dma_fsm //////////////////////////////////////////////////////////////////////////// // The DMA_TLB_MISS FSM handles an IOTLB miss. It blocks the TGT_FSM. // Input argument is: // - r_iotlb_vaddr // - r_dma_tlb_req (reset) // - r_tlb_miss_init_req (set) // - r_config_tlb_req (reset) // - r_tlb_dma_untreated (set) // // This fsm searchs the requested PTE on the prefetch buffer. // In case of miss, it accesses the XRAM to find the missing TLB entry, // It bypass the first level page table access if possible. // It directly updates the iotlb, and writes into the // r_mmu_ins_* or r_mmu_data* error reporting registers. //////////////////////////////////////////////////////////////////////////////////// switch (r_dma_tlb_fsm.read()) { case DMA_TLB_IDLE: { if(r_config_tlb_req) { r_config_tlb_req = false; r_waiting_transaction = false; r_dma_tlb_fsm = DMA_TLB_INVAL_CHECK; // Request from CONFIG FSM following an PTE invalidation signal by OS } // Miss in IOTLB else if(r_dma_tlb_req.read()) { // Checking prefetch buffer, by the virtual address if(!r_miss_buf_first_level) { if( r_miss_buf_valid && (r_miss_buf_vaddr_begin.read() == (r_iotlb_vaddr.read()& ~PTE2_LINE_OFFSET & ~K_PAGE_OFFSET_MASK))) { // Hit size_t pte_offset = (r_iotlb_vaddr.read()& PTE2_LINE_OFFSET)>>12; uint32_t pte_flags = r_miss_buf_data[2*pte_offset]; uint32_t pte_ppn = r_miss_buf_data[2*pte_offset+1]; //because PTE2 is 2 words long // Bit valid checking if ( not ( pte_flags & PTE_V_MASK) ) // unmapped { //must not occur! std::cout << "IOMMU ERROR : " << name() << " DMA_TLB_IDLE state" << std::endl << "The Page Table entry ins't valid (unmapped)" << std::endl; r_tlb_error_type = MMU_READ_PT2_UNMAPPED; r_dma_tlb_error_req = true; r_dma_tlb_req = false; #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " PTE2 Unmapped" << std::hex << " / paddr = " << r_iotlb_paddr.read() << std::hex << " / PTE (first word) = " << pte_flags << std::endl; } #endif break; } r_iotlb_pte_flags = pte_flags; r_iotlb_pte_ppn = pte_ppn; r_dma_tlb_fsm = DMA_TLB_PTE2_SELECT; #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " Hit on the prefetch buffer for PTE2:" << " PTE_FLAGS = " << std::hex << pte_flags << " PTE_PPN = " << std::hex << pte_ppn << std::endl; } #endif break; } } else // First level entries on buffer. Unused if only small pages { if( r_miss_buf_valid && (r_miss_buf_vaddr_begin.read() == (r_iotlb_vaddr.read()& ~PTE1_LINE_OFFSET & ~M_PAGE_OFFSET_MASK ))) // The virtual address corresponds to one entry on the buffer line { // Hit size_t pte_offset = (r_iotlb_vaddr.read()& PTE1_LINE_OFFSET)>>21; uint32_t pte_flags = r_miss_buf_data[pte_offset]; // Bit valid checking if ( not ( pte_flags & PTE_V_MASK) ) // unmapped { //must not occur! std::cout << "IOMMU ERROR " << name() << "DMA_TLB_IDLE state" << std::endl << "The Page Table entry ins't valid (unmapped)" << std::endl; r_tlb_error_type = MMU_READ_PT1_UNMAPPED; r_dma_tlb_error_req = true; r_dma_tlb_req = false; #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " First level entry Unmapped" << std::hex << " / paddr = " << r_iotlb_paddr.read() << std::hex << " / PTE = " << pte_flags << std::endl; } #endif break; } if( pte_flags & PTE_T_MASK ) // PTD : me must access PT2 { // register bypass r_iotlb.set_bypass( r_iotlb_vaddr.read(), pte_flags & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1), 0); //nline, unused //&PTE2 = PTBA + IX2 * 8 // ps: PAGE_K_NBITS corresponds also to the size of a second level page table r_iotlb_paddr = (paddr_t)(pte_flags & ((1<<(m_paddr_nbits-PAGE_K_NBITS))-1)) << PAGE_K_NBITS | (paddr_t)(((r_iotlb_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3); r_tlb_miss_init_req = true; r_tlb_miss_type = PTE2_MISS; r_dma_tlb_fsm = DMA_TLB_WAIT_TRANSACTION; #ifdef INSTRUMENTATION m_cpt_iotlbmiss_transaction++; #endif #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " Hit on prefetch, but it is a PTD.Search PTE2" << std::hex << " / paddr = " << r_iotlb_paddr.read() << std::hex << " / PTD = " << pte_flags << std::endl; } #endif } else // PTE1 : we must update the TLB // Should not occur if working only with small pages { r_iotlb_pte_flags = pte_flags; r_dma_tlb_fsm = DMA_TLB_PTE1_SELECT; #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " Success. Big page" << std::hex << " / paddr = " << r_iotlb_paddr.read() << std::hex << " / PTE1 = " << pte_flags << std::endl; } #endif } break; } } r_dma_tlb_fsm = DMA_TLB_MISS; #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " Miss on prefetch." << std::hex << " / vaddr = " << r_iotlb_vaddr.read() << std::endl; } #endif } break; } ///////////////////// case DMA_TLB_MISS: // handling all tlb miss { uint32_t ptba = 0; //28 bits en TSAR bool bypass; paddr_t pte_paddr; // evaluate bypass in order to skip first level page table access bypass = r_iotlb.get_bypass(r_iotlb_vaddr.read(), &ptba); //Request to MISS_INIT_FSM to start transaction on Direct Network if ( not bypass ) // Read PTE1/PTD1 in XRAM { // VOIR CONVENTION >> 13 pte_paddr = (paddr_t)((r_iommu_ptpr.read()) << (INDEX1_NBITS+2)) | (paddr_t)((r_iotlb_vaddr.read() >> PAGE_M_NBITS) << 2); r_iotlb_paddr = pte_paddr; r_tlb_miss_init_req = true; r_tlb_miss_type = PTE1_MISS; r_dma_tlb_fsm = DMA_TLB_WAIT_TRANSACTION; #ifdef INSTRUMENTATION m_cpt_iotlbmiss_transaction++; #endif } else // Read PTE2 in XRAM { //&PTE2 = PTBA + IX2 * 8 pte_paddr = (paddr_t)ptba << PAGE_K_NBITS | (paddr_t)(r_iotlb_vaddr.read()&PTD_ID2_MASK)>>(PAGE_K_NBITS-3); r_iotlb_paddr = pte_paddr; r_tlb_miss_init_req = true; r_tlb_miss_type = PTE2_MISS; r_dma_tlb_fsm = DMA_TLB_WAIT_TRANSACTION; #ifdef INSTRUMENTATION m_cpt_iotlbmiss_transaction++; #endif } #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " IOTLB miss"; std::cout << " / VADDR = " << std::hex << r_iotlb_vaddr.read() << " / BYPASS = " << bypass << " / PTE_ADR = " << pte_paddr << std::endl; } #endif break; } ///////////////////////// case DMA_TLB_PTE1_GET: // Try to read a PT1 entry in the miss buffer { uint32_t entry; paddr_t line_number = (paddr_t)((r_iotlb_paddr.read())&(CACHE_LINE_MASK)); size_t word_position = (size_t)( ((r_iotlb_paddr.read())&(~CACHE_LINE_MASK))>>2 ); // Hit test. Just to verify. // Hit must happen, since we've just finished its' miss transaction bool hit = (r_miss_buf_valid && (r_miss_buf_tag.read()== line_number) ); assert(hit and "Error: No hit on prefetch buffer after Miss Transaction"); entry = r_miss_buf_data[word_position]; // Bit valid checking if ( not ( entry & PTE_V_MASK) ) // unmapped { //must not occur! std::cout << "IOMMU ERROR " << name() << "DMA_TLB_IDLE state" << std::endl << "The Page Table entry ins't valid (unmapped)" << std::endl; r_tlb_error_type = MMU_READ_PT1_UNMAPPED; r_dma_tlb_error_req = true; r_dma_tlb_req = false; r_dma_tlb_fsm = DMA_TLB_IDLE; #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " First level entry Unmapped" << std::hex << " / paddr = " << r_iotlb_paddr.read() << std::hex << " / PTE = " << entry << std::endl; } #endif break; } if( entry & PTE_T_MASK ) // PTD : me must access PT2 { // register bypass r_iotlb.set_bypass( r_iotlb_vaddr.read(), entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1), 0); //nline, unused //&PTE2 = PTBA + IX2 * 8 // ps: PAGE_K_NBITS corresponds also to the size of a second level page table r_iotlb_paddr = (paddr_t)(entry & ((1<<(m_paddr_nbits-PAGE_K_NBITS))-1)) << PAGE_K_NBITS | (paddr_t)(((r_iotlb_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3); r_tlb_miss_init_req = true; r_tlb_miss_type = PTE2_MISS; r_dma_tlb_fsm = DMA_TLB_WAIT_TRANSACTION; #ifdef INSTRUMENTATION m_cpt_iotlbmiss_transaction++; #endif #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " Success. Search PTE2" << std::hex << " / paddr = " << r_iotlb_paddr.read() << std::hex << " / PTD = " << entry << std::endl; } #endif } else // PTE1 : we must update the IOTLB // Should not occur if working only with small pages { r_iotlb_pte_flags = entry; r_dma_tlb_fsm = DMA_TLB_PTE1_SELECT; #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " Success. Big page" << std::hex << " / paddr = " << r_iotlb_paddr.read() << std::hex << " / PTE1 = " << entry << std::endl; } #endif } break; } //////////////////////////// case DMA_TLB_PTE1_SELECT: // select a slot for PTE1 { size_t way; size_t set; r_iotlb.select( r_iotlb_vaddr.read(), true, // PTE1 &way, &set ); #ifdef INSTRUMENTATION m_cpt_iotlb_read++; #endif #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " Select a slot in IOTLB:"; std::cout << " way = " << std::dec << way << " / set = " << set << std::endl; } #endif r_iotlb_way = way; r_iotlb_set = set; r_dma_tlb_fsm = DMA_TLB_PTE1_UPDT; break; } ////////////////////////// case DMA_TLB_PTE1_UPDT: // write a new PTE1 in tlb // not necessary to treat the L/R bit { //(OLD) paddr_t nline = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2); uint32_t pte = r_iotlb_pte_flags.read(); r_miss_paddr = (paddr_t)( ((r_iotlb_pte_flags.read() & PPN1_MASK) << 21) | (r_iotlb_vaddr.read()& M_PAGE_OFFSET_MASK) ); // update TLB r_iotlb.write( true, // 2M page pte, 0, // argument unused for a PTE1 r_iotlb_vaddr.read(), r_iotlb_way.read(), r_iotlb_set.read(), 0 ); //we set nline = 0 #ifdef INSTRUMENTATION m_cpt_iotlb_write++; #endif #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " write PTE1 in IOTLB"; std::cout << " / set = " << std::dec << r_iotlb_set.read() << " / way = " << r_iotlb_way.read() << std::endl; r_iotlb.printTrace(); } #endif // next state r_dma_tlb_fsm = DMA_TLB_RETURN; // exit sub-fsm break; } ///////////////////////// case DMA_TLB_PTE2_GET: // Try to read a PTE2 (64 bits) in the miss buffer { uint32_t pte_flags; uint32_t pte_ppn; paddr_t line_number = (paddr_t)((r_iotlb_paddr.read())&(CACHE_LINE_MASK)); size_t word_position = (size_t)( ((r_iotlb_paddr.read())&(~CACHE_LINE_MASK))>>2 ); // Hit test. Just to verify. bool hit = (r_miss_buf_valid && (r_miss_buf_tag.read()== line_number) ); assert(hit and "Error: No hit on prefetch buffer after Miss Transaction"); pte_flags= r_miss_buf_data[word_position]; pte_ppn= r_miss_buf_data[word_position+1]; //because PTE2 is 2 words long // Bit valid checking if ( not ( pte_flags & PTE_V_MASK) ) // unmapped { //must not occur! std::cout << "IOMMU ERROR " << name() << "DMA_TLB_IDLE state" << std::endl << "The Page Table entry ins't valid (unmapped)" << std::endl; r_tlb_error_type = MMU_READ_PT2_UNMAPPED; r_dma_tlb_error_req = true; r_dma_tlb_req = false; r_dma_tlb_fsm = DMA_TLB_IDLE; #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " PTE2 Unmapped" << std::hex << " / paddr = " << r_iotlb_paddr.read() << std::hex << " / PTE = " << pte_flags << std::endl; } #endif break; } r_iotlb_pte_flags = pte_flags; r_iotlb_pte_ppn = pte_ppn; r_dma_tlb_fsm = DMA_TLB_PTE2_SELECT; #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " Mapped:" << " PTE_FLAGS = " << std::hex << pte_flags << " PTE_PPN = " << std::hex << pte_ppn << std::endl; } #endif break; } //////////////////////////// case DMA_TLB_PTE2_SELECT: // select a slot for PTE2 { size_t way; size_t set; r_iotlb.select( r_iotlb_vaddr.read(), false, // PTE2 &way, &set ); #ifdef INSTRUMENTATION m_cpt_iotlb_read++; #endif #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " Select a slot in IOTLB:"; std::cout << " way = " << std::dec << way << " / set = " << set << std::endl; } #endif r_iotlb_way = way; r_iotlb_set = set; r_dma_tlb_fsm = DMA_TLB_PTE2_UPDT; break; } ////////////////////////// case DMA_TLB_PTE2_UPDT: // write a new PTE2 in tlb // not necessary to treat the L/R bit { //(OLD) paddr_t nline = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2); uint32_t pte_flags = r_iotlb_pte_flags.read(); uint32_t pte_ppn = r_iotlb_pte_ppn.read(); r_miss_paddr = (paddr_t)( ((r_iotlb_pte_ppn.read() & PPN2_MASK) << 12) | (r_iotlb_vaddr.read()& K_PAGE_OFFSET_MASK) ); // update TLB for a PTE2 r_iotlb.write( false, // 4K page pte_flags, pte_ppn, r_iotlb_vaddr.read(), r_iotlb_way.read(), r_iotlb_set.read(), 0 ); // nline = 0 #ifdef INSTRUMENTATION m_cpt_iotlb_write++; #endif #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " write PTE2 in IOTLB"; std::cout << " / set = " << std::dec << r_iotlb_set.read() << " / way = " << r_iotlb_way.read() << std::endl; r_iotlb.printTrace(); } #endif // next state r_dma_tlb_fsm = DMA_TLB_RETURN; // exit sub-fsm break; } /////////////////////// case DMA_TLB_WAIT_TRANSACTION: { // CONFIG FSM request following a invalidation signal sent by OS. if(r_config_tlb_req) { r_config_tlb_req = false; r_waiting_transaction = true; r_dma_tlb_fsm = DMA_TLB_INVAL_CHECK; } #ifdef INSTRUMENTATION m_cost_iotlbmiss_transaction++; #endif if ( not r_tlb_miss_init_req ) // Miss transaction is done { if ( r_miss_init_error.read() ) // bus error { r_miss_init_error = false; r_tlb_error_type = MMU_READ_DATA_ILLEGAL_ACCESS; r_dma_tlb_error_req = true; r_dma_tlb_req = false; r_dma_tlb_fsm = DMA_TLB_IDLE; } else if(r_tlb_miss_type == PTE1_MISS) { r_dma_tlb_fsm = DMA_TLB_PTE1_GET; } else { r_dma_tlb_fsm = DMA_TLB_PTE2_GET; } } break; } /////////////////////// case DMA_TLB_RETURN: // return to caller depending on tlb miss type { #if DEBUG_DMA_TLB if ( m_debug_dma_tlb_fsm ) { std::cout << " IOTLB MISS completed" << std::endl; } #endif r_dma_tlb_req = false; r_tlb_dma_untreated = true; r_dma_tlb_fsm = DMA_TLB_IDLE; break; } ////////////////////// case DMA_TLB_INVAL_CHECK: // request from CONFIG FSM to invalidate all PTE on a given line // This state checks the necessity to invalidate prefetch buffer { // If a transaction is pending, no need to invalidate the prefetch // We can ignore it, since we'll replace the line. // The new line is necessarily up-to-date if(!r_waiting_transaction.read() && r_miss_buf_valid) { if(!r_miss_buf_first_level) { if( r_miss_buf_vaddr_begin.read() == (r_config_tlb_inval_vaddr.read()& ~PTE2_LINE_OFFSET) ) // The virtual address corresponds to one entry on the buffer line { r_miss_buf_valid = false; //change here for individual invalidation } } else // First level entries on buffer. Unused if only small pages { if( r_miss_buf_vaddr_begin.read() == (r_config_tlb_inval_vaddr.read()& ~PTE1_LINE_OFFSET) ) // The virtual address corresponds to one entry on the buffer line { r_miss_buf_valid = false; //change here for individual invalidation } } } // Invalidation on IOTLB bool ok; ok = r_iotlb.inval(r_config_tlb_inval_vaddr.read()); if(r_waiting_transaction.read()) r_dma_tlb_fsm =DMA_TLB_WAIT_TRANSACTION; else r_dma_tlb_fsm = DMA_TLB_IDLE; break; } } //end switch r_dma_tlb_fsm ///////////////////////////////////////////////////////////////////// // The CONFIG_CMD_FSM is similar to the DMA_CMD_FSM, but without miss TLB treatment. // It controls the following ressources: // - r_config_cmd_fsm // // - r_config_cmd_rsp_erase_req (set) // - r_config_tlb_req (set) ///////////////////////////////////////////////////////////////////// switch( r_config_cmd_fsm.read() ) { ////////////// case CONFIG_CMD_IDLE: { if ( p_vci_tgt_config.cmdval.read() ) { #if DEBUG_CONFIG_CMD if( m_debug_config_cmd_fsm ) { std::cout << " Configuration command received!" <>2); // Treatement of received command // Verifies error, tests if the the command is for IOB itself // To IOB itself if(m_segment_config.contains(config_paddr)) { if(!read && (cell == IOB_IOMMU_PTPR)) r_config_cmd_fsm = CONFIG_CMD_PTPR_WRITE; else if(read && (cell == IOB_IOMMU_PTPR)) r_config_cmd_fsm = CONFIG_CMD_PTPR_READ; else if(!read && (cell == IOB_IOMMU_ACTIVE)) r_config_cmd_fsm = CONFIG_CMD_ACTIVE_WRITE; else if(read && (cell == IOB_IOMMU_ACTIVE)) r_config_cmd_fsm = CONFIG_CMD_ACTIVE_READ; else if(read && (cell == IOB_IOMMU_BVAR)) r_config_cmd_fsm = CONFIG_CMD_BVAR_READ; else if(read && (cell == IOB_IOMMU_ETR)) r_config_cmd_fsm = CONFIG_CMD_ETR_READ; else if(read && (cell == IOB_IOMMU_BAD_ID)) r_config_cmd_fsm = CONFIG_CMD_BAD_ID_READ; // PTE invalidation signaled by the OS else if(!read && (cell == IOB_INVAL_PTE)) r_config_cmd_fsm = CONFIG_CMD_INVAL_REQ; else if(!read && (cell == IOB_IT_ADDR_IOMMU_LO)) r_config_cmd_fsm = CONFIG_CMD_IT_ADDR_IOMMU_WRITE_1; else if(read && (cell == IOB_IT_ADDR_IOMMU_LO)) r_config_cmd_fsm = CONFIG_CMD_IT_ADDR_IOMMU_READ_1; else if( !read && ((cell >= IOB_IT_ADDR_BEGIN)&& ( cell< (IOB_IT_ADDR_BEGIN +2*m_nb_periph-1) ) ) ) { // a factor two shows up because the registres come in couples r_it_index = (cell - IOB_IT_ADDR_BEGIN)/2; r_config_cmd_fsm = CONFIG_CMD_IT_ADDR_WRITE_1; } else if( read && ((cell >= IOB_IT_ADDR_BEGIN)&& (cell< (IOB_IT_ADDR_BEGIN +2*m_nb_periph-1))) ) { r_it_index = (cell - IOB_IT_ADDR_BEGIN)/2; r_config_cmd_fsm = CONFIG_CMD_IT_ADDR_READ_1; } else //Error. Wrong address, or invalid operation. { if(read) r_config_error_type = READ_ERROR; else r_config_error_type = WRITE_ERROR; r_config_cmd_fsm = CONFIG_CMD_ERROR_WAIT; } } // Must route the command to the correct IO else { if(!p_vci_tgt_config.eop.read()) { //Error if(read) r_config_error_type = READ_ERROR; else r_config_error_type = WRITE_ERROR; r_config_cmd_fsm = CONFIG_CMD_ERROR_WAIT; } // Find the corresponding address on IO Space // int tgt_index = m_routing_table_config[config_paddr]; //#if DEBUG_CONFIG_CMD //if( m_debug_config_cmd_fsm ) //{ // std::cout << " Routing a configuration packet" < Check the TRT" << std::endl; } #endif size_t wok_index = 0; bool wok = !m_transaction_tab_config.full(wok_index); if ( wok ) // TRT isn't full. Write the new transaction. { r_config_cmd_trt_index = (vci_trdid_t)wok_index; r_config_cmd_fsm = CONFIG_CMD_TRT_SET; } else // wait an empty entry in TRT { r_config_cmd_fsm = CONFIG_CMD_TRT_WAIT; r_config_cmd_rsp_erase_req = true; #if DEBUG_CONFIG_CMD if( m_debug_config_cmd_fsm ) { std::cout << " TRT is full. Going to TRT_WAIT state" << std::endl; } #endif #ifdef INSTRUMENTATION m_cpt_trt_config_full++; #endif } } break; } //////////////// case CONFIG_CMD_TRT_WAIT: // release the lock protecting the transaction tab // waits that RSP erases an entry { #ifdef INSTRUMENTATION m_cpt_trt_config_full_cost++; #endif // CONFIG_RSP will notify an erase action by reseting this register if(!r_config_cmd_rsp_erase_req.read()) { r_config_cmd_fsm = CONFIG_CMD_TRT_LOCK; // take the lock again } break; } //////////////////////// case CONFIG_CMD_TRT_SET: // register a new transaction in TRT { if ( r_alloc_trt_config_fsm.read() == ALLOC_TRT_CONFIG_CMD ) { m_transaction_tab_config.set( r_config_cmd_trt_index.read(), p_vci_tgt_config.srcid.read(), p_vci_tgt_config.trdid.read() ); r_config_cmd_fsm = CONFIG_CMD_FIFO_PUT; #if DEBUG_CONFIG_CMD if( m_debug_config_cmd_fsm ) { std::cout << " Set a new entry in TRT" << std::endl; } #endif } break; } /////////////////////// case CONFIG_CMD_FIFO_PUT: { if ( p_vci_tgt_config.cmdval && m_config_cmd_addr_fifo.wok() ) { config_cmd_fifo_put = true; if( p_vci_tgt_config.eop ) r_config_cmd_fsm = CONFIG_CMD_IDLE; #if DEBUG_CONFIG_CMD if( m_debug_config_cmd_fsm ) { std::cout << " Push into config_cmd_fifo:" << " address = " << std::hex << r_config_vaddr.read() << " srcid = " << std::dec << m_srcid_config << " trdid = " << r_config_cmd_trt_index.read() << " wdata = " << std::hex << p_vci_tgt_config.wdata.read() << " be = " << p_vci_tgt_config.be.read() << " plen = " << std::dec << p_vci_tgt_config.plen.read() << std::endl; } #endif } break; } /////////////////////////////// // Private Configuration States /////////////////////////////// ////////////////// case CONFIG_CMD_PTPR_WRITE: // Convention- The word received is in the format: // 00000 BASE_ADDRESS[39:13] // Same pattern as in iommu_ptpr register { if ( p_vci_tgt_config.cmdval.read() && m_config_local_data_fifo.wok() && r_dma_tlb_fsm == DMA_TLB_IDLE ) { // This verification could have been done on IDLE state // It would save us one cycle if ( !p_vci_tgt_config.eop.read() ) { std::cout << "CONFIG_CMD ERROR " << name() << " CONFIG_CMD_PTPR_WRITE state" << std::endl; std::cout << " PTPR write command must contain one single flit" << std::endl; r_config_error_type = WRITE_ERROR; r_config_cmd_fsm = CONFIG_CMD_ERROR_WAIT; break; } // Depends on the convention r_iommu_ptpr = (uint32_t)(p_vci_tgt_config.wdata.read()); config_local_fifo_put = true; r_config_cmd_fsm = CONFIG_CMD_IDLE; #if DEBUG_CONFIG_CMD if( m_debug_config_cmd_fsm ) { std::cout << " PTPR received:" << "r_iommu_ptpr = " << std::hex << (p_vci_tgt_config.wdata.read()) < Read and erase entry" << std::endl; } #endif uint32_t trdid_iospace = p_vci_ini_config.rtrdid.read(); r_config_rsrcid = (vci_srcid_t)m_transaction_tab_config.readSrcid(trdid_iospace); r_config_rtrdid = (vci_trdid_t)m_transaction_tab_config.readTrdid(trdid_iospace); m_transaction_tab_config.erase(trdid_iospace); if (r_config_cmd_rsp_erase_req.read()) r_config_cmd_rsp_erase_req = false; r_config_rsp_fsm = CONFIG_RSP_FIFO_PUT; } break; } ////////////////// case CONFIG_RSP_FIFO_PUT: { if(p_vci_ini_config.rspval.read() && m_config_rsp_data_fifo.wok()) { config_rsp_fifo_put = true; if(p_vci_ini_config.reop.read()) r_config_rsp_fsm = CONFIG_RSP_IDLE; #if DEBUG_CONFIG_RSP if( m_debug_config_rsp_fsm ) { std::cout << " Push into rsp_fifo:" << " rsrcid = " << std::dec << r_config_rsrcid.read() << " rtrdid = " << r_config_rtrdid.read() << " rdata = " << std::hex << p_vci_ini_config.rdata.read() << std::endl; } #endif } break; } } // end switch CONFIG_RSP FSM //////////////////////////////////////////////////////////////////////////// // The ALLOC_TRT_CONFIG fsm allocates the access to the Transaction Table (m_transaction_tab_config) // with a round robin priority between 2 user FSMs : // - CONFIG_CMD : to set a new entry // - CONFIG_RSP : to read and erase an entry // The ressource is always allocated. //////////////////////////////////////////////////////////////////////////////////// switch ( r_alloc_trt_config_fsm.read() ) { /////////////////// case ALLOC_TRT_CONFIG_CMD: { if ( r_config_cmd_fsm.read() != CONFIG_CMD_TRT_LOCK ) { if (r_config_rsp_fsm.read() == CONFIG_RSP_TRT_LOCK) r_alloc_trt_config_fsm = ALLOC_TRT_CONFIG_RSP; } } /////////////////// case ALLOC_TRT_CONFIG_RSP: { if (r_config_rsp_fsm.read() != CONFIG_RSP_TRT_LOCK) { if (r_config_cmd_fsm.read() == CONFIG_CMD_TRT_LOCK) r_alloc_trt_config_fsm = ALLOC_TRT_CONFIG_CMD; } } } // end switch r_alloc_trt_config_fsm //////////////////////////////////////////////////////////////////////////// // The MISS_INIT FSM sends a page table entry miss request into Direct Noc // It controls the following ressources: // - r_miss_init_fsm // - r_tlb_miss_init_req (reset) // - r_miss_buf_data // - r_miss_buf_valid // - r_miss_buf_tag //////////////////////////////////////////////////////////////////////////////////// // Building the interruption vector (systematically) uint32_t irq_demands = 0; for ( size_t i = 0; i Send write (irq) command to XICU" << " irq ID = " << std::dec << r_irq_chosen.read() << " new mask = " << std::hex << (r_irq_mask.read() & ~(1< Send read (tlb entry) request to MEM CACHE: " << " | address : "<< std::hex <<(paddr_t)((r_iotlb_paddr.read())& CACHE_LINE_MASK) << std::endl; } #endif } break; } ////////////////// case MISS_INIT_TLB_MISS_RSP: { if ( p_vci_ini_miss.rspval.read() ) { if ( (p_vci_ini_miss.rerror.read()&0x1) != 0 ) // error reported { r_miss_init_error = true; if ( p_vci_ini_miss.reop.read() ) { r_miss_init_fsm = MISS_INIT_IDLE_IRQ; r_tlb_miss_init_req = false; } #if DEBUG_MISS_INIT if( m_debug_miss_init_fsm ) { std::cout << " ERROR " << std::endl; } #endif } else { bool eop = p_vci_ini_miss.reop.read(); #if DEBUG_MISS_INIT if( m_debug_miss_init_fsm ) { std::cout << " Response from Mem Cache to a read (tlb entry) transaction. Count = " << r_miss_rsp_cpt.read() <<" | Data = " << std::hex << p_vci_ini_miss.rdata.read() << std::endl; } #endif assert(((eop == (r_miss_rsp_cpt.read() == (m_words-1))) ) and "Error : invalid length for a response from MEM CACHE"); r_miss_buf_data[r_miss_rsp_cpt] = (uint32_t)p_vci_ini_miss.rdata.read(); r_miss_rsp_cpt = r_miss_rsp_cpt.read() + 1; if ( eop ) { r_tlb_miss_init_req = false; //reset the request flip-flop r_miss_init_fsm = MISS_INIT_IDLE_IRQ; } } } break; } } // end switch r_miss_init_fsm ////////////////////////////////// // Fifo consumption arbitration // ////////////////////////////////// // Round Robin priority for CONFIG_RSP FIFO consumption r_config_rsp_fifo_local_priority = ! r_config_rsp_fifo_local_priority.read(); //DMA CMD dma_cmd_fifo_get = (p_vci_ini_dma.cmdack.read() && m_dma_cmd_addr_fifo.rok()); // DMA RSP dma_rsp_fifo_get = (p_vci_tgt_dma.rspack.read() && m_dma_rsp_data_fifo.rok()); // CONFIG CMD config_cmd_fifo_get = (p_vci_ini_config.cmdack.read() && m_config_cmd_addr_fifo.rok() ); // CONFIG RSP, detemines wich fifo to consume if(r_config_rsp_fifo_local_priority) { if(m_config_local_data_fifo.rok()) config_local_fifo_get = p_vci_tgt_config.rspack.read(); else if (m_config_rsp_data_fifo.rok()) config_rsp_fifo_get = p_vci_tgt_config.rspack.read(); } else { if (m_config_rsp_data_fifo.rok()) config_rsp_fifo_get = p_vci_tgt_config.rspack.read(); else if(m_config_local_data_fifo.rok()) config_local_fifo_get = p_vci_tgt_config.rspack.read(); } /////////////// //DMA_CMD Fifo /////////////// if(r_miss_interrupt) { m_dma_cmd_addr_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_paddr.read() ); m_dma_cmd_cmd_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_cmd.read() ); m_dma_cmd_contig_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_contig.read() ); m_dma_cmd_cons_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_cons.read() ); m_dma_cmd_plen_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_plen.read() ); m_dma_cmd_wrap_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_wrap.read() ); m_dma_cmd_cfixed_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_cfixed.read() ); m_dma_cmd_clen_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_clen.read() ); m_dma_cmd_srcid_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, m_srcid_dma ); //r_miss_srcid.read() m_dma_cmd_trdid_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_trdid.read() ); m_dma_cmd_pktid_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_pktid.read() ); m_dma_cmd_data_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_data[r_dma_cmd_count.read()-1] ); m_dma_cmd_be_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_miss_be[r_dma_cmd_count.read()-1] ); m_dma_cmd_eop_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, (r_dma_cmd_count.read() == 1) ); } else { m_dma_cmd_addr_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_dma_paddr.read() ); m_dma_cmd_cmd_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.cmd.read() ); m_dma_cmd_contig_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.contig.read() ); m_dma_cmd_cons_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.cons.read() ); m_dma_cmd_plen_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.plen.read() ); m_dma_cmd_wrap_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.wrap.read() ); m_dma_cmd_cfixed_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.cfixed.read() ); m_dma_cmd_clen_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.clen.read() ); m_dma_cmd_srcid_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, m_srcid_dma ); m_dma_cmd_trdid_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, r_dma_cmd_trt_index.read() ); m_dma_cmd_pktid_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.pktid.read() ); m_dma_cmd_data_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.wdata.read() ); // TODO change // For 64bits XRAM m_dma_cmd_be_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.be.read() ); m_dma_cmd_eop_fifo.update( dma_cmd_fifo_get, dma_cmd_fifo_put, p_vci_tgt_dma.eop.read() ); } /////////////// //DMA_RSP Fifo /////////////// if(r_dma_rsp_fsm.read() == DMA_RSP_FIFO_ERROR_PUT) { m_dma_rsp_data_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, 0 ); m_dma_rsp_rsrcid_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, r_iommu_bad_id.read() ); m_dma_rsp_rtrdid_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, r_dma_error_trdid.read() ); m_dma_rsp_rpktid_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, r_dma_error_pktid.read() ); m_dma_rsp_reop_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, true ); m_dma_rsp_rerror_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, r_dma_error_type.read() ); } else { m_dma_rsp_data_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, p_vci_ini_dma.rdata.read() ); m_dma_rsp_rsrcid_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, r_dma_rsrcid.read() ); m_dma_rsp_rtrdid_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, r_dma_rtrdid.read() ); m_dma_rsp_rpktid_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, p_vci_ini_dma.rpktid.read() ); m_dma_rsp_reop_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, p_vci_ini_dma.reop.read() ); m_dma_rsp_rerror_fifo.update( dma_rsp_fifo_get, dma_rsp_fifo_put, p_vci_ini_dma.rerror.read() ); } ////////////////// //CONFIG_CMD Fifo ////////////////// m_config_cmd_addr_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, r_config_vaddr.read() ); m_config_cmd_cmd_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.cmd.read() ); m_config_cmd_contig_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.contig.read() ); m_config_cmd_cons_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.cons.read() ); m_config_cmd_plen_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.plen.read() ); m_config_cmd_wrap_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.wrap.read() ); m_config_cmd_cfixed_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.cfixed.read() ); m_config_cmd_clen_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.clen.read() ); m_config_cmd_srcid_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, m_srcid_config ); m_config_cmd_trdid_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, r_config_cmd_trt_index.read() ); m_config_cmd_pktid_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.pktid.read() ); m_config_cmd_data_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.wdata.read() ); m_config_cmd_be_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.be.read() ); m_config_cmd_eop_fifo.update( config_cmd_fifo_get, config_cmd_fifo_put, p_vci_tgt_config.eop.read() ); ////////////////// //CONFIG_RSP Fifo ////////////////// m_config_rsp_data_fifo.update( config_rsp_fifo_get, config_rsp_fifo_put, p_vci_ini_config.rdata.read() ); m_config_rsp_rsrcid_fifo.update( config_rsp_fifo_get, config_rsp_fifo_put, r_config_rsrcid.read() ); m_config_rsp_rtrdid_fifo.update( config_rsp_fifo_get, config_rsp_fifo_put, r_config_rtrdid.read() ); m_config_rsp_rpktid_fifo.update( config_rsp_fifo_get, config_rsp_fifo_put, p_vci_ini_config.rpktid.read() ); m_config_rsp_reop_fifo.update( config_rsp_fifo_get, config_rsp_fifo_put, p_vci_ini_config.reop.read() ); m_config_rsp_rerror_fifo.update( config_rsp_fifo_get, config_rsp_fifo_put, p_vci_ini_config.rerror.read() ); /////////////////////// //CONFIG Local RSP Fifo /////////////////////// m_config_local_rsrcid_fifo.update( config_local_fifo_get, config_local_fifo_put, p_vci_tgt_config.srcid.read() ); m_config_local_rtrdid_fifo.update( config_local_fifo_get, config_local_fifo_put, p_vci_tgt_config.trdid.read() ); m_config_local_rpktid_fifo.update( config_local_fifo_get, config_local_fifo_put, p_vci_tgt_config.pktid.read() ); switch( r_config_cmd_fsm.read() ) { case CONFIG_CMD_PTPR_WRITE: case CONFIG_CMD_ACTIVE_WRITE: case CONFIG_CMD_IT_ADDR_IOMMU_WRITE_2: case CONFIG_CMD_IT_ADDR_WRITE_2: case CONFIG_CMD_INVAL: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, 0); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, WRITE_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, true ); break; case CONFIG_CMD_PTPR_READ: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, r_iommu_ptpr.read()); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, READ_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, true ); break; case CONFIG_CMD_ACTIVE_READ: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, r_iommu_active.read()); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, READ_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, true ); break; case CONFIG_CMD_BVAR_READ: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, r_iommu_bvar.read()); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, READ_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, true ); break; case CONFIG_CMD_ETR_READ: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, r_iommu_etr.read()); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, READ_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, true ); break; case CONFIG_CMD_BAD_ID_READ: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, r_iommu_bad_id.read()); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, READ_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, true ); break; case CONFIG_CMD_IT_ADDR_IOMMU_READ_1: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, (uint32_t)(r_it_addr_iommu.read() & 0xFFFFFFFF) ); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, READ_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, false ); break; case CONFIG_CMD_IT_ADDR_IOMMU_READ_2: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, (uint32_t)((r_it_addr_iommu.read()>>32)&0xFF) ); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, READ_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, true ); break; case CONFIG_CMD_IT_ADDR_READ_1: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, (uint32_t)(r_it_addr[r_it_index.read()] & 0xFFFFFFFF) ); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, READ_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, false ); break; case CONFIG_CMD_IT_ADDR_READ_2: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, (uint32_t)((r_it_addr[r_it_index.read()]>>32)&0xFF) ); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, READ_OK ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, true ); break; case CONFIG_CMD_ERROR_RSP: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, 0); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, r_config_error_type.read() ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, true ); break; default: m_config_local_data_fifo.update( config_local_fifo_get, config_local_fifo_put, 0); m_config_local_rerror_fifo.update( config_local_fifo_get, config_local_fifo_put, 0 ); m_config_local_reop_fifo.update( config_local_fifo_get, config_local_fifo_put, false ); break; } } // end transition() /////////////////////// tmpl(void)::genMoore() /////////////////////// { ////////////////// // DMA Commands // ////////////////// // VCI initiator command on the xram network if(m_dma_cmd_addr_fifo.rok()) //&& p_vci_ini_dma.cmdack.read()) { p_vci_ini_dma.cmdval = true; #if NEW_XRAM_VCI p_vci_ini_dma.address = (paddr_t_x)(m_dma_cmd_addr_fifo.read() >> 6 ) #else p_vci_ini_dma.address = m_dma_cmd_addr_fifo.read(); #endif p_vci_ini_dma.be = m_dma_cmd_be_fifo.read(); p_vci_ini_dma.cmd = m_dma_cmd_cmd_fifo.read(); p_vci_ini_dma.contig = m_dma_cmd_contig_fifo.read(); #if NEW_XRAM_VCI //TODO for 64 bits field #else p_vci_ini_dma.wdata = m_dma_cmd_data_fifo.read(); // The first is in param_x // the second in param_io #endif p_vci_ini_dma.eop = m_dma_cmd_eop_fifo.read(); p_vci_ini_dma.cons = m_dma_cmd_cons_fifo.read(); p_vci_ini_dma.plen = m_dma_cmd_plen_fifo.read(); p_vci_ini_dma.wrap = m_dma_cmd_wrap_fifo.read(); p_vci_ini_dma.cfixed = m_dma_cmd_cfixed_fifo.read(); p_vci_ini_dma.clen = m_dma_cmd_clen_fifo.read(); p_vci_ini_dma.trdid = m_dma_cmd_trdid_fifo.read(); p_vci_ini_dma.pktid = m_dma_cmd_pktid_fifo.read(); p_vci_ini_dma.srcid = m_dma_cmd_srcid_fifo.read(); } else { p_vci_ini_dma.cmdval = false; p_vci_ini_dma.address = 0; p_vci_ini_dma.be = 0; p_vci_ini_dma.cmd = vci_param_x::CMD_NOP; p_vci_ini_dma.contig = false; p_vci_ini_dma.wdata = 0; p_vci_ini_dma.eop = false; p_vci_ini_dma.cons = true; p_vci_ini_dma.plen = 0; p_vci_ini_dma.wrap = false; p_vci_ini_dma.cfixed = false; p_vci_ini_dma.clen = 0; p_vci_ini_dma.trdid = 0; p_vci_ini_dma.pktid = 0; } // VCI target command on the IO network // it depends on the DMA_CMD FSM state switch ( r_dma_cmd_fsm.read() ) { case DMA_CMD_IDLE: case DMA_CMD_TRT_LOCK: case DMA_CMD_TRT_WAIT: case DMA_CMD_TRT_SET: p_vci_tgt_dma.cmdack = false; break; case DMA_CMD_FIFO_PUT: case DMA_CMD_FIFO_MISS_PUT: p_vci_tgt_dma.cmdack = m_dma_cmd_addr_fifo.wok(); break; case DMA_CMD_TLB_MISS_WAIT: p_vci_tgt_dma.cmdack = false; break; case DMA_CMD_TLB_MISS_STORE: p_vci_tgt_dma.cmdack = true; break; case DMA_CMD_ERROR: p_vci_tgt_dma.cmdack = !r_dma_cmd_error_req.read(); break; }// end switch r_dma_cmd_fsm ////////////////// // DMA Responses// ////////////////// // VCI target response on the IO network if(m_dma_rsp_data_fifo.rok()) { p_vci_tgt_dma.rspval = true; p_vci_tgt_dma.rsrcid = m_dma_rsp_rsrcid_fifo.read(); p_vci_tgt_dma.rtrdid = m_dma_rsp_rtrdid_fifo.read(); p_vci_tgt_dma.rpktid = m_dma_rsp_rpktid_fifo.read(); #if NEW_XRAM_VCI //TODO for 64 bit data field #else p_vci_tgt_dma.rdata = m_dma_rsp_data_fifo.read(); // The first is in param_io // the second in param_x #endif p_vci_tgt_dma.rerror = m_dma_rsp_rerror_fifo.read(); p_vci_tgt_dma.reop = m_dma_rsp_reop_fifo.read(); } else { p_vci_tgt_dma.rspval = false; p_vci_tgt_dma.rsrcid = 0; p_vci_tgt_dma.rdata = 0; p_vci_tgt_dma.rpktid = 0; p_vci_tgt_dma.rtrdid = 0; p_vci_tgt_dma.rerror = 0; p_vci_tgt_dma.reop = false; } // VCI initiator response on the Xram Network // it depends on the DMA_RSP FSM state switch ( r_dma_rsp_fsm.read() ) { case DMA_RSP_IDLE: case DMA_RSP_TRT_LOCK: case DMA_RSP_FIFO_ERROR_PUT: { p_vci_ini_dma.rspack = false; break; } case DMA_RSP_FIFO_PUT: { p_vci_ini_dma.rspack = m_dma_rsp_data_fifo.wok(); break; } }// end switch r_dma_rsp_fsm ///////////////////// // CONFIG Commands // ///////////////////// // VCI initiator command on the IO network if(m_config_cmd_addr_fifo.rok()) { p_vci_ini_config.cmdval = true; #if NEW_XRAM_VCI p_vci_ini_config.address = (paddr_t_x)(m_config_cmd_addr_fifo.read() >> 6 ) #else p_vci_ini_config.address = m_config_cmd_addr_fifo.read(); #endif p_vci_ini_config.be = (vci_be_t_x)m_config_cmd_be_fifo.read(); p_vci_ini_config.cmd = m_config_cmd_cmd_fifo.read(); p_vci_ini_config.contig = m_config_cmd_contig_fifo.read(); #if NEW_XRAM_VCI //TODO #else p_vci_ini_config.wdata = (vci_data_t_x)m_config_cmd_data_fifo.read(); // The first is in param_io // the second in param_d #endif p_vci_ini_config.eop = m_config_cmd_eop_fifo.read(); p_vci_ini_config.cons = m_config_cmd_cons_fifo.read(); p_vci_ini_config.plen = m_config_cmd_plen_fifo.read(); p_vci_ini_config.wrap = m_config_cmd_wrap_fifo.read(); p_vci_ini_config.cfixed = m_config_cmd_cfixed_fifo.read(); p_vci_ini_config.clen = m_config_cmd_clen_fifo.read(); p_vci_ini_config.trdid = m_config_cmd_trdid_fifo.read(); p_vci_ini_config.pktid = m_config_cmd_pktid_fifo.read(); } else { p_vci_ini_config.cmdval = false; p_vci_ini_config.address = 0; p_vci_ini_config.be = 0; p_vci_ini_config.cmd = vci_param_io::CMD_NOP; p_vci_ini_config.contig = false; p_vci_ini_config.wdata = 0; p_vci_ini_config.eop = false; p_vci_ini_config.cons = true; p_vci_ini_config.plen = 0; p_vci_ini_config.wrap = false; p_vci_ini_config.cfixed = false; p_vci_ini_config.clen = 0; p_vci_ini_config.trdid = 0; p_vci_ini_config.pktid = 0; } // VCI target command on the Direct network // it depends on the CONFIG_CMD FSM state switch ( r_config_cmd_fsm.read() ) { case CONFIG_CMD_IDLE: case CONFIG_CMD_TRT_LOCK: case CONFIG_CMD_TRT_WAIT: case CONFIG_CMD_TRT_SET: case CONFIG_CMD_IT_ADDR_IOMMU_READ_1: case CONFIG_CMD_IT_ADDR_READ_1: case CONFIG_CMD_ERROR_RSP: case CONFIG_CMD_INVAL_REQ: p_vci_tgt_config.cmdack = false; break; case CONFIG_CMD_FIFO_PUT: case CONFIG_CMD_PTPR_WRITE: case CONFIG_CMD_PTPR_READ: case CONFIG_CMD_ACTIVE_WRITE: case CONFIG_CMD_ACTIVE_READ: case CONFIG_CMD_BVAR_READ: case CONFIG_CMD_ETR_READ: case CONFIG_CMD_BAD_ID_READ: case CONFIG_CMD_IT_ADDR_IOMMU_WRITE_2: case CONFIG_CMD_IT_ADDR_IOMMU_READ_2: case CONFIG_CMD_IT_ADDR_WRITE_2: case CONFIG_CMD_IT_ADDR_READ_2: case CONFIG_CMD_INVAL: p_vci_tgt_config.cmdack = m_config_cmd_addr_fifo.wok(); break; case CONFIG_CMD_IT_ADDR_IOMMU_WRITE_1: case CONFIG_CMD_IT_ADDR_WRITE_1: case CONFIG_CMD_ERROR_WAIT: p_vci_tgt_config.cmdack = true; break; default: p_vci_tgt_config.cmdack = false; break; }// end switch r_config_cmd_fsm ///////////////////// // CONFIG Responses// ///////////////////// // VCI target response on the Direct network if(r_config_rsp_fifo_local_priority) { if( m_config_local_data_fifo.rok() ) { p_vci_tgt_config.rspval = true; p_vci_tgt_config.rsrcid = m_config_local_rsrcid_fifo.read(); p_vci_tgt_config.rtrdid = m_config_local_rtrdid_fifo.read(); p_vci_tgt_config.rpktid = m_config_local_rpktid_fifo.read(); p_vci_tgt_config.rdata = (vci_data_t)m_config_local_data_fifo.read(); p_vci_tgt_config.rerror = m_config_local_rerror_fifo.read(); p_vci_tgt_config.reop = m_config_local_reop_fifo.read(); } else if(m_config_rsp_data_fifo.rok() ) { p_vci_tgt_config.rspval = true; p_vci_tgt_config.rsrcid = m_config_rsp_rsrcid_fifo.read(); p_vci_tgt_config.rtrdid = m_config_rsp_rtrdid_fifo.read(); p_vci_tgt_config.rpktid = m_config_rsp_rpktid_fifo.read(); p_vci_tgt_config.rdata = (vci_data_t)m_config_rsp_data_fifo.read(); // The first is in param_d // the second in param_io p_vci_tgt_config.rerror = m_config_rsp_rerror_fifo.read(); p_vci_tgt_config.reop = m_config_rsp_reop_fifo.read(); } else { p_vci_tgt_config.rspval = false; p_vci_tgt_config.rsrcid = 0; p_vci_tgt_config.rdata = 0; p_vci_tgt_config.rpktid = 0; p_vci_tgt_config.rtrdid = 0; p_vci_tgt_config.rerror = 0; p_vci_tgt_config.reop = false; } } else { if(m_config_rsp_data_fifo.rok() ) { p_vci_tgt_config.rspval = true; p_vci_tgt_config.rsrcid = m_config_rsp_rsrcid_fifo.read(); p_vci_tgt_config.rtrdid = m_config_rsp_rtrdid_fifo.read(); p_vci_tgt_config.rpktid = m_config_rsp_rpktid_fifo.read(); p_vci_tgt_config.rdata = (vci_data_t)m_config_rsp_data_fifo.read(); // The first is in param_d // the second in param_io p_vci_tgt_config.rerror = m_config_rsp_rerror_fifo.read(); p_vci_tgt_config.reop = m_config_rsp_reop_fifo.read(); } else if( m_config_local_data_fifo.rok() ) { p_vci_tgt_config.rspval = true; p_vci_tgt_config.rsrcid = m_config_local_rsrcid_fifo.read(); p_vci_tgt_config.rtrdid = m_config_local_rtrdid_fifo.read(); p_vci_tgt_config.rpktid = m_config_local_rpktid_fifo.read(); p_vci_tgt_config.rdata = (vci_data_t)m_config_local_data_fifo.read(); p_vci_tgt_config.rerror = m_config_local_rerror_fifo.read(); p_vci_tgt_config.reop = m_config_local_reop_fifo.read(); } else { p_vci_tgt_config.rspval = false; p_vci_tgt_config.rsrcid = 0; p_vci_tgt_config.rdata = 0; p_vci_tgt_config.rpktid = 0; p_vci_tgt_config.rtrdid = 0; p_vci_tgt_config.rerror = 0; p_vci_tgt_config.reop = false; } } // VCI initiator response on the IO Network // it depends on the CONFIG_RSP FSM state switch ( r_config_rsp_fsm.read() ) { case CONFIG_RSP_IDLE: case CONFIG_RSP_TRT_LOCK: p_vci_ini_config.rspack = false; break; case CONFIG_RSP_FIFO_PUT: p_vci_ini_config.rspack = m_config_rsp_data_fifo.wok(); break; }// end switch r_config_rsp_fsm //////////////////////////////////////////////////////////////// // VCI initiator command and response on from the Direct network // for Miss Transactions p_vci_ini_miss.srcid = m_srcid_miss; switch ( r_miss_init_fsm.read() ) { case MISS_INIT_IDLE_MISS: case MISS_INIT_IDLE_IRQ: p_vci_ini_miss.cmdval = false; p_vci_ini_miss.address = 0; p_vci_ini_miss.be = 0; p_vci_ini_miss.cmd = vci_param_d::CMD_NOP; p_vci_ini_miss.contig = false; p_vci_ini_miss.wdata = 0; p_vci_ini_miss.eop = false; p_vci_ini_miss.cons = true; p_vci_ini_miss.plen = 0; p_vci_ini_miss.wrap = false; p_vci_ini_miss.cfixed = false; p_vci_ini_miss.clen = 0; p_vci_ini_miss.trdid = 0; p_vci_ini_miss.pktid = 0; p_vci_ini_miss.rspack = false; break; case MISS_INIT_IRQ_CMD: p_vci_ini_miss.cmdval = true; p_vci_ini_miss.address = (paddr_t)r_it_addr[r_irq_chosen.read()]; p_vci_ini_miss.wdata = 0; p_vci_ini_miss.plen = vci_param_d::B; p_vci_ini_miss.trdid = 0; p_vci_ini_miss.cmd = vci_param_d::CMD_READ; p_vci_ini_miss.eop = true; p_vci_ini_miss.be = 0xF; p_vci_ini_miss.pktid = 0; p_vci_ini_miss.cons = false; p_vci_ini_miss.wrap = false; p_vci_ini_miss.contig = true; p_vci_ini_miss.clen = 0; p_vci_ini_miss.cfixed = false; break; case MISS_INIT_IRQ_RSP: case MISS_INIT_TLB_MISS_RSP: p_vci_ini_miss.cmdval = false; p_vci_ini_miss.address = 0; p_vci_ini_miss.be = 0; p_vci_ini_miss.cmd = vci_param_d::CMD_NOP; p_vci_ini_miss.contig = false; p_vci_ini_miss.wdata = 0; p_vci_ini_miss.eop = false; p_vci_ini_miss.cons = true; p_vci_ini_miss.plen = 0; p_vci_ini_miss.wrap = false; p_vci_ini_miss.cfixed = false; p_vci_ini_miss.clen = 0; p_vci_ini_miss.trdid = 0; p_vci_ini_miss.pktid = 0; p_vci_ini_miss.rspack = true; break; case MISS_INIT_TLB_MISS_CMD: p_vci_ini_miss.cmdval = true; p_vci_ini_miss.address = (paddr_t)((r_iotlb_paddr.read())& CACHE_LINE_MASK); p_vci_ini_miss.wdata = 0x00000000; p_vci_ini_miss.plen = m_words*(vci_param_d::B); p_vci_ini_miss.trdid = 0; //could be used as the index on a miss transaction table p_vci_ini_miss.cmd = vci_param_d::CMD_READ; p_vci_ini_miss.eop = true; p_vci_ini_miss.be = 0xF; p_vci_ini_miss.pktid = 0; p_vci_ini_miss.cons = false; p_vci_ini_miss.wrap = false; p_vci_ini_miss.contig = true; p_vci_ini_miss.clen = 0; p_vci_ini_miss.cfixed = false; break; } // end switch r_miss_init_fsm } // end genMoore }} // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4