282 | | To increase the simulation speed, the TLM-T wrapper is the cache controller itself, and it is implemented as the class ''' !VciXcache'''. This class contains the SC_THREAD '''execLoop()''' implementing the PDES process, and the '''m_time''' member variable implementing the associated local clock. |
283 | | |
284 | | The class '''!VciXcache''' inherit the class '''tlmt::!ModuleBase''', that is the basis for all TLM-T modules. |
285 | | |
286 | | This class contains the member variable '''m_iss''' representing the processor ISS. The type of the '''m_iss''' variable is defined by the template parameter '''iss_t'''. |
| 282 | To increase the simulation speed, the TLM-T wrapper is the cache controller itself, and it is implemented as the class ''' !VciXcache'''. |
| 283 | This class contains the SC_THREAD '''execLoop()''' implementing the PDES process, and the '''c0''' member variable of |
| 284 | type '''tlmt_core::tlmt_thread_context''' that mainly contains the associated local clock. |
| 285 | |
| 286 | The class '''!VciXcache''' inherits from the class '''tlmt::!ModuleBase''', that is the root class for all TLM-T modules. |
| 287 | |
| 288 | This class contains the member variable '''m_iss''' representing the processor ISS. The type of the '''m_iss''' variable is defined by |
| 289 | the template parameter '''iss_t'''. |
290 | | The class '''!VciXcache''' contain a member variable '''p_vci''', of type '''!VciInitPort''', to send VCI command packets, and receive VCI response packets. |
291 | | |
292 | | This class also contains the member variable '''p_irq''', that is a pointer to an array of ports of type '''SynchroInPort'''. This array represents the interrupt ports. The number N of interrupt ports depends on the wrapped processor, an is defined by the '''n_irq''' member variable of the '''iss_t''' class. |
293 | | |
294 | | The '''execLoop()''' function contains an infinite loop. One iteration in this loop corresponds to one cycle for the local clock (or more, as the thread is suspended in case of MISS). |
295 | | |
296 | | The cache behavior is specifically described by the '''cacheAccess()''' method, that is a member function of the class '''!VciXcache''', and is called by '''execLoop()''' at each cycle. This function has the following prototype : |
| 293 | The class '''!VciXcache''' contains a member variable '''p_vci''', of type '''!VciInit''', to send VCI command packets, and receive VCI |
| 294 | response packets. |
| 295 | |
| 296 | This class also contains the member variable '''p_irq''', which is a pointer to an array of ports of type '''tlmt_core::tlmt_in<bool>'''. |
| 297 | This array represents the interrupt ports. The number N of interrupt ports depends on the wrapped processor, and is defined by |
| 298 | the '''n_irq''' member variable of the '''iss_t''' class. |
| 299 | |
| 300 | The '''execLoop()''' function contains an infinite loop. One iteration in this loop corresponds to one cycle for the local |
| 301 | clock (or more, if the thread is suspended in case of a cache miss). |
| 302 | |
| 303 | The cache behavior is specifically described by the '''xcacheAccess()''' method, which is a member function of the |
| 304 | class '''!VciXcache'''. This function is called by '''execLoop()''' at each cycle. This function has the following prototype : |
298 | | void cacheAccess(icache_request_t *ireq, |
299 | | dcache_request_t *dreq, |
300 | | xcache_response_t *rsp) |
301 | | }}} |
302 | | |
303 | | The '''icache_request_t''', '''dcache_request_t''', and '''xcache_response_t''' classes represent the instruction and data requests, and the cache response respectively : |
304 | | {{{ |
305 | | class icache_request_t { |
306 | | bool valid ; |
307 | | uint32_t address ; |
308 | | }; |
309 | | class dcache_request_t { |
310 | | bool valid ; |
311 | | enum DataAccessType type ; |
312 | | uint32_t address ; |
313 | | uint32_t wdata ; |
314 | | }; |
315 | | class xcache_response_t { |
316 | | bool iber ; |
317 | | uint32_t instruction ; |
318 | | bool dber ; |
319 | | uint32_t rdata ; |
320 | | }; |
321 | | }}} |
322 | | |
323 | | The '''cacheAccess()''' function détermines the actions to be done : |
324 | | * In case of data or instruction MISS, the '''cacheAccess()''' function sends the proper VCI command packet on the '''p_vci''' port, and the '''exedcLoop()''' thread is suspended. |
325 | | * In case of data write, the the '''cacheAccess()''' function sends the proper VCI command packet on the '''p_vci''' port, but the '''exedcLoop()''' thread is not suspended. |
326 | | |
327 | | At each iteration in the execution loop, the '''cacheAccess()''' method updates the local clock (variable '''m_time''') : |
| 306 | |
| 307 | void xcacheAccess( |
| 308 | bool &ins_asked, // The iss requests a new instruction |
| 309 | uint32_t &ins_addr, // at the address ins_addr |
| 310 | |
| 311 | bool &mem_asked, // In parallel, the iss can ask for a memory access |
| 312 | enum iss_t::DataAccessType &mem_type // of type mem_type, |
| 313 | uint32_t &mem_addr, // and at address mem_addr |
| 314 | uint32_t &mem_wdata, // Eventually, the iss also provides the write data |
| 315 | |
| 316 | uint32_t &mem_rdata, // In return, the xcacheAccess function returns the read data |
| 317 | bool &mem_dber, // and a potential data bus error |
| 318 | uint32_t &ins_rdata, // as well as the next instruction to be executed |
| 319 | bool &ins_iber // and a potential instruction bu error |
| 320 | ); |
| 321 | |
| 322 | }}} |
| 323 | |
| 324 | The '''xcacheAccess()''' function détermines the actions to be done by the cache: |
| 325 | * In case of data or instruction MISS, the '''xcacheAccess()''' function sends the appropriate VCI command packet on |
| 326 | the '''p_vci''' port, and the '''exedcLoop()''' thread is suspended. |
| 327 | * In case of data write, the the '''xcacheAccess()''' function sends the appropriate VCI command packet on |
| 328 | the '''p_vci''' port, but the '''exedcLoop()''' thread is not suspended. Thus, the processor is not stalled |
| 329 | |
| 330 | At each iteration in the execution loop, the '''xcacheAccess()''' method updates the local clock (through the variable '''c0''') : |
331 | | The SystemC TLM-T model for the '''!VciXcache''' module is presented below : |
332 | | {{{ |
333 | | template<typename iss_t, typename vci_param> |
334 | | class VciXcache<iss_t> : tlmt::BaseModule { |
335 | | |
336 | | public : |
337 | | /////// ports /////// |
338 | | VciInitiatorPort<vci_param> p_vci ; |
339 | | SynchroInPort * p_irq ; |
340 | | |
341 | | /////// constructor ///// |
342 | | VciXcache (sc_module_name name, |
343 | | uint32_t initiatorIndex, |
344 | | uint32_t processorIdent, |
345 | | uint32_t lookahead, |
346 | | uint32_t dcache_nlines, |
347 | | uint32_t dcache_nwords, |
348 | | uint32_t icache_nlines, |
349 | | uint32_t icache_nwords) |
350 | | BaseModule(name), |
351 | | m_iss(processorIdent), |
352 | | m_time(0) |
353 | | { |
354 | | p_vci(« vci », this, &VciXcache::rspReceived, &m_time) , |
355 | | for (uint32_t i = 0 ; i < iss_t::n_irq ; i++) { |
356 | | new(&p_irq[i])SynchroInPort ("irq", i, this, &VciXcache::irqReceived) ; |
357 | | } |
358 | | m_initiator_index = initiatorIndex ; |
359 | | m_counter = 0 ; |
360 | | m_lookahead = lookahead ; |
361 | | m_icache_nlines = icache_nlines ; |
362 | | mi_icache_nwords = icache_nwords ; |
363 | | m_dcache_nlines = dcache_nlines ; |
364 | | m_dcache_nwords = dcache_nwords ; |
365 | | SC_THREAD(execLoop) ; |
366 | | } // end constructor |
367 | | |
368 | | private : |
369 | | /////// member variables |
370 | | tlmt_time m_time ; |
371 | | sc_event m_rsp_received ; |
372 | | iss_t m_iss ; |
373 | | bool m_write_error ; |
374 | | uint32_t m_dcache_nlines ; |
375 | | uint32_t m_dcache_nwords ; |
376 | | uint32_t m_icache_nlines ; |
377 | | uint32_t m_icache_nwords ; |
378 | | uint32_t m_initiator_index ; |
379 | | uint32_t m_lookahead ; |
380 | | uint32_t m_counter ; |
381 | | bool m_irqpending[iss_t;;n_irq]; |
382 | | uint32_t m_irqtime[iss_t::n_irq] ; |
383 | | vci_cmd_t m_cmd ; |
384 | | ////////////////// thread |
385 | | void execLoop() |
386 | | { |
387 | | icache_request_t icache_req ; // The Icache request |
388 | | dcache_request_t dcache_req ; // The Dcache request |
389 | | xcache_response_t xcache_rsp ; // The Xcache response |
390 | | uint32_t irqword ; |
391 | | while(1) { |
392 | | // execute one cycle |
393 | | if (m_iss.isBusy() { |
394 | | m_iss.nullStep() ; |
395 | | } else { |
396 | | /////////// cache access |
397 | | m_iss.getInstructionRequest(icache_req.valid, |
398 | | icache_req.address) ; |
399 | | m_iss.getDataRequest(dcache_req.valid, |
400 | | dcache_req.type, |
401 | | dcache_req.address, |
402 | | dcache_req.wdata) |
403 | | xcacheAccess(&icache_req, &dcache_req, &xcache_rsp) ; |
404 | | if ( icache_req.valid ) m_iss.setInstruction(xcache_rsp.iber, xcache_rsp.instruction) ; |
405 | | if ( dcache_req.valid ) m_iss.setDataResponse(xcache_rsp.dber, xcache_rsp.rdata) ; |
406 | | //////// handling interrupts |
407 | | irqword = 0 ; |
408 | | for ( size_t i = 0 ; i < iss_t ::n_irq ; i++) { |
409 | | if( m_irqpending[i] && m_irqtime[i] <= get_time()) irqword |= (1<<i); |
410 | | } |
411 | | m_iss.setIrq(irqword) ; |
412 | | ///////// handling asynchronous bus error |
413 | | if ( m_write_error ) { |
414 | | setWriteBerr() ; |
415 | | m_write_error = false ; |
416 | | } |
417 | | m_iss.step() ; |
418 | | } // end cycle |
419 | | // lookahead management |
420 | | m_counter++ ; |
421 | | if (m_counter >= m_lookahead) { |
422 | | m_counter = 0 ; |
423 | | wait(SC_ZERO_TIME) ; |
424 | | } // end if lookahead |
425 | | } // end while(1) |
426 | | } // end execLoop() |
427 | | |
428 | | ///////////////////////////////////////////////////// |
429 | | void cacheAccess(icache_request_t ireq, |
430 | | dcache_request_t dreq, |
431 | | xcache_response_t rsp) |
432 | | { |
433 | | ... |
434 | | } // end cacheAccess() |
435 | | |
436 | | //////////////////////////// |
437 | | void rspReceived(vci_rsp_t rsp, |
438 | | uint32_t time) |
439 | | { |
440 | | if ( rsp.cmd == VCI_CMD_write ) { // asynchronous bus error signaling |
441 | | m_write_error = ( rsp.error != 0 ) ; |
442 | | } |
443 | | if ( rsp.cmd == VCI_CMD_READ ) { // time update & cache activation |
444 | | m_time.updateTime( time + rsp.length ) ; |
445 | | notify( m_rsp_received ) ; |
446 | | } |
447 | | } // end rspReceived() |
448 | | |
449 | | //////////////////////////// |
450 | | void irqReceived(bool val, |
451 | | uint32_t time |
452 | | size_t index) |
453 | | { |
454 | | m_irqpending[index] = val ; |
455 | | m_irqtime[p_irq[index] = time ; |
456 | | } // end irqReceived() |
457 | | } // end class VciXcache |
458 | | }}} |
459 | | |
460 | | |
461 | | |
| 334 | The SystemC TLM-T model for the '''!VciXcache''' module is presented below in the following files |
| 335 | |