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

Last change on this file was 1022, checked in by cfuguet, 11 years ago

Fixing warning with new compiler's versions.

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