⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dram_main.c

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2002 The Board of Trustees of the University of Illinois and *                    William Marsh Rice University * Copyright (c) 2002 The University of Utah * Copyright (c) 2002 The University of Notre Dame du Lac * * All rights reserved. * * Based on RSIM 1.0, developed by: *   Professor Sarita Adve's RSIM research group *   University of Illinois at Urbana-Champaign and     William Marsh Rice University *   http://www.cs.uiuc.edu/rsim and http://www.ece.rice.edu/~rsim/dist.html * ML-RSIM/URSIM extensions by: *   The Impulse Research Group, University of Utah *   http://www.cs.utah.edu/impulse *   Lambert Schaelicke, University of Utah and University of Notre Dame du Lac *   http://www.cse.nd.edu/~lambert *   Mike Parker, University of Utah *   http://www.cs.utah.edu/~map * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal with the Software without restriction, including without * limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, subject to the following * conditions: * * 1. Redistributions of source code must retain the above copyright notice, *    this list of conditions and the following disclaimers.  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimers in the *    documentation and/or other materials provided with the distribution. * 3. Neither the names of Professor Sarita Adve's RSIM research group, *    the University of Illinois at Urbana-Champaign, William Marsh Rice *    University, nor the names of its contributors may be used to endorse *    or promote products derived from this Software without specific prior *    written permission.  * 4. Neither the names of the ML-RSIM project, the URSIM project, the *    Impulse research group, the University of Utah, the University of *    Notre Dame du Lac, nor the names of its contributors may be used to *    endorse or promote products derived from this software without specific *    prior written permission.  * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS WITH THE SOFTWARE.  */#include <stdio.h>#include "DRAM/cqueue.h"#include "Memory/mmc.h"#include "DRAM/dram_param.h"#include "DRAM/dram.h"/* * Master Memory controller uses this function to send a memory access  * to DRAM backend.  */void  DRAM_recv_request(int nodeid, mmc_trans_t *ptrans,			unsigned paddr, int size, int is_write){  dram_info_t   *pdb = NID2DRAM(nodeid);  dram_sa_bus_t *psabus;  EVENT	        *pevent;  dram_trans_t  *dtrans = DRAM_new_transaction(pdb, ptrans, paddr, size, 					       is_write);#ifdef TRACEDRAM  if (dparam.trace_on)    {      if(!dparam.trace_max || (dram_trace_count < dparam.trace_max))	{	  fprintf(dram_trace_fp, "%d 0x%x %d %d %.0f\n", 		  (ptrans->dspr) ? (ptrans->dspr->index+1): 0, paddr, 		  (dtrans->is_write) ? 1 : 0, size, YS__Simtime);	  dram_trace_count++;	}    }#endif   if (dparam.sim_on == 0)     {       DRAM_nosim_start(pdb, dtrans);       return;     }   /*    * - If SA bus is busy, push the request into the waiting queue.    * - Otherwise, use it to send the request to the relevant bank.     *   Function DRAM_arrive_smc() will be activated to     *   receive this access after "sa_bus_cycles" cycles.    */   if (pdb->sa_bus.busy)     {       if (cbuf_full(pdb->sa_bus.waiters))         YS__errmsg(nodeid, "SA bus's waiting queue is full.\n");       else         cbuf_enqueue(pdb->sa_bus.waiters, dtrans);     }   else     {       pdb->sa_bus.busy = 1;       pevent        = pdb->sa_bus.pevent;       pevent->uptr3 = dtrans;       schedule_event(pevent, YS__Simtime + dparam.sa_bus_cycles);     }}/* * A DRAM access request arrives at slave memory controller. */ void DRAM_arrive_smc(void){  dram_info_t    *pdb    = YS__ActEvnt->uptr1;  dram_sa_bus_t  *psabus = YS__ActEvnt->uptr2;  dram_trans_t   *dtrans = YS__ActEvnt->uptr3;  unsigned        paddr  = dtrans->paddr;  dram_bank_t    *pbank  = DRAM_paddr_to_bank(pdb, paddr);    /*   * Collect statitics.   */  if (dparam.collect_stats)    {      psabus->count++;      psabus->cycles += YS__Simtime - dtrans->time;      dtrans->time = YS__Simtime;    }  /*    * - If the bank is busy, put the access into the waiting queue.   * - otherwise, access the bank.   */  if (pbank->busy || pbank->chip->refresh_on)    {      if (Bank_queue_full(&(pbank->waiters)))	YS__errmsg(0, "pbank->waiters are full\n");      if (dparam.collect_stats)	{	  pbank->stats.queue_waits++;	  pbank->stats.queue_len += pbank->waiters.size;	}            Bank_queue_enqueue(&(pbank->waiters), dtrans);      pdb->total_bwaiters++;    }  else    DRAM_access_bank(pdb, dtrans, YS__Simtime);    /*    * - If there are other requests waiting on the same slave address bus,   *   grant this slave address bus to the next one in FIFO order.   * - Otherwise, free the slave address bus.   */  if (cbuf_empty(psabus->waiters))    {      psabus->busy = 0;    }  else    {      EVENT  *pevent = psabus->pevent;      dtrans = (dram_trans_t *) cbuf_dequeue(psabus->waiters);            if (dparam.collect_stats)	{	  psabus->waits++;	  psabus->wcycles += YS__Simtime - dtrans->time;	}      pevent->uptr3   = dtrans;      schedule_event(pevent, YS__Simtime + dparam.sa_bus_cycles);    }}/* * Access to specific bank.  */void  DRAM_access_bank(dram_info_t *pdb, dram_trans_t *dtrans,		       rsim_time_t starttime){  dram_bank_t  *pbank = DRAM_paddr_to_bank(pdb, dtrans->paddr);  /*   * Collect statistics.   */  if (dparam.collect_stats)    {      if (dtrans->is_write) 	pbank->stats.writes++;      else 	pbank->stats.reads++;    }  /*    * Access specified DRAMs.    */  if (dparam.scheduler_on)    {      switch (dparam.dram_type)	{	case SDRAM:	  DRAM_access_SDRAM_bank(pdb, dtrans, starttime);	  break;	case RDRAM:	  DRAM_access_RDRAM_bank(pdb, dtrans, starttime);	  break;	default:	  YS__errmsg(pdb->nodeid, "Unkown DRAM type %d\n", dparam.dram_type);	}    }  else    DRAM_access_bank_aux1(pdb, dtrans, starttime);  /*   * Remember the type of last access. It's used for Precharge command.   */  pbank->last_type = dtrans->is_write;}/* * Called when the scheduler is NOT on. In this case, each bank access * is a constant delay. */void  DRAM_access_bank_aux1(dram_info_t *pdb, dram_trans_t *dtrans,			    rsim_time_t starttime){  unsigned      paddr  = dtrans->paddr;  mmc_trans_t  *ptrans = dtrans->ptrans;  int           size   = dtrans->size;  dram_bank_t  *pbank  = DRAM_paddr_to_bank(pdb, paddr);  EVENT        *pevent = pbank->pevent;  rsim_time_t   nxttime;     /*   * Call DRAM_bank_done when the access is done.   */  if (dparam.dram_type == RDRAM)     nxttime = YS__Simtime + dparam.co2d_cycles +       dparam.dtime.r.PACKET * (size >> dparam.width_shift);  else    nxttime = YS__Simtime + dparam.co2d_cycles +        dparam.dtime.s.PACKET * (size >> dparam.width_shift);  pbank->busy = dtrans;  schedule_event(pevent, nxttime);}/* * Access Synchronous DRAM. Please see SDRAM documents for the details  * on SDRAM timing. The basic idea here is to find the earliest  * possible time to start the access. */void  DRAM_access_SDRAM_bank(dram_info_t *pdb, dram_trans_t *dtrans, 			     rsim_time_t starttime){  mmc_trans_t   *ptrans    = dtrans->ptrans;  unsigned       paddr     = dtrans->paddr;  unsigned       size      = dtrans->size;  int            row_num   = paddr >> dparam.row_shift;  dram_bank_t   *pbank     = DRAM_paddr_to_bank(pdb, paddr);  dram_rd_bus_t *prdbus    = DRAM_bankid_to_rd_bus(pdb, pbank->id);  dram_chip_t   *pchip     = pbank->chip;  EVENT         *pevent    = pbank->pevent;  int            cas_count = size >> dparam.width_shift;  rsim_time_t    bus_busy, start_time, wcycles, delay;  int            hit_row;     /*   * First, find out if it hits/misses on the hot row.   */  if (row_num == pbank->hot_row && pbank->expire > starttime )     hit_row = 1;  else    hit_row = 0;  pbank->hitmiss = (pbank->hitmiss << 1) | (row_num == pbank->hot_row);  /*   * Add command2command delay.   */  if (pchip->last_bank == pbank->id)    {      prdbus->busy_until += dparam.dtime.s.CCD;      pchip->ras_busy    += dparam.dtime.s.CCD;    }  else    {      prdbus->busy_until += dparam.dtime.s.RRD;      pchip->ras_busy    += dparam.dtime.s.RRD;    }    /*    * Find the earliest time that the access can be initiated, for   * the RD bus concern only.    */  if (hit_row)    bus_busy = prdbus->busy_until;  else    bus_busy = prdbus->busy_until -       (dparam.dtime.s.RAS + dparam.dtime.s.RCD);  if (!dtrans->is_write)    bus_busy -= dparam.dtime.s.AA;  start_time = MAX(MAX(pchip->ras_busy, bus_busy), starttime);  /*   * Collect statistics.   */  if (dparam.collect_stats)    {      prdbus->count++;      prdbus->cycles += dparam.dtime.s.PACKET * cas_count;      if (start_time == bus_busy)	{	  wcycles = bus_busy - MAX(pchip->ras_busy, starttime);	  if (wcycles > 0)	    {	      prdbus->waits++;	      prdbus->wcycles += wcycles;	      prdbus->cycles  += wcycles;	    }	}            if (hit_row)	{	  if (dtrans->is_write)	    pbank->stats.write_hits++;	  else  	    pbank->stats.read_hits++;	}      else if (pbank->expire > starttime)	{	  if (dtrans->is_write)	    pbank->stats.write_misses++;	  else  	    pbank->stats.read_misses++;	}            pbank->stats.queue_cycles += start_time - dtrans->time;      dtrans->time = start_time;      if (start_time < prdbus->busy_until)	pbank->stats.overlap += prdbus->busy_until - start_time;    }    /*   * Close the current hot row if it exists.    */  if (!hit_row && pbank->expire > starttime)    {      start_time += dparam.dtime.s.RP;      if (pbank->last_type == DRAM_WRITE)	start_time += dparam.dtime.s.DAL;    }    /*   * Update the states of control signals (RAS/CAS) and data signals.   *    */  if (hit_row)    {      pchip->ras_busy    = start_time + dparam.dtime.s.PACKET * cas_count;      prdbus->busy_until = start_time + dparam.dtime.s.PACKET * cas_count;    }  else    {      pchip->ras_busy    = start_time + dparam.dtime.s.RAS + 	dparam.dtime.s.RCD + 	dparam.dtime.s.PACKET * cas_count;      prdbus->busy_until = start_time + dparam.dtime.s.RAS + 	dparam.dtime.s.RCD + 	dparam.dtime.s.PACKET * cas_count;    }    if (!dtrans->is_write)    prdbus->busy_until += dparam.dtime.s.AA;    /*    * - If the hot row is remained open after this access, remember   *   the active row.   * - Otherwise, enable auto precharge operation.   */  pbank->hot_row = row_num;  if (dtrans->open_row)    {      pbank->expire  = start_time + dparam.row_hold_time;    }  else    {      if (dtrans->is_write)	{	  pchip->ras_busy    += dparam.dtime.s.DPL + dparam.dtime.s.RP;	  prdbus->busy_until += dparam.dtime.s.DPL + dparam.dtime.s.RP;	}      else	{	  delay = dparam.dtime.s.RP - cas_count;	  if (delay < 0)            delay = 0;	  pchip->ras_busy    += dparam.dtime.s.DPL + delay;	  prdbus->busy_until += dparam.dtime.s.DPL + delay;	}            pbank->expire = 0;    }  pchip->last_bank = pbank->id;  pchip->last_type = dtrans->is_write;    /*   * Schedule the event to call DRAM_bank_done when this access is done.   */  pbank->busy = dtrans;  schedule_event(pevent, prdbus->busy_until);}/* * Direct Rambus DRAM. Please consult RDRAM documents for the  * details on RDRAM timing. */void DRAM_access_RDRAM_bank(dram_info_t *pdb, dram_trans_t *dtrans,			    rsim_time_t starttime){  mmc_trans_t   *ptrans    = dtrans->ptrans;  unsigned       paddr     = dtrans->paddr;  unsigned       size      = dtrans->size;  int            row_num   = paddr >> dparam.row_shift;  dram_bank_t   *pbank     = DRAM_paddr_to_bank(pdb, paddr);  dram_rd_bus_t *prdbus    = DRAM_bankid_to_rd_bus(pdb, pbank->id);  dram_chip_t   *pchip     = pbank->chip;  EVENT         *pevent    = pbank->pevent;  int            cas_count = size >> dparam.width_shift;  int            hit_row;  rsim_time_t    cas_busy, bus_busy, bank_start, start_time, wcycles;     /*   * First, find out if it hits/misses on the hot row.   */  if (row_num == pbank->hot_row && pbank->expire > starttime)     hit_row = 1;  else    hit_row = 0;  pbank->hitmiss = (pbank->hitmiss << 1) | (row_num == pbank->hot_row);  /*    * Find the earliest free time for RAS bus. (Figure 13/14, p 28,29.)   */  if (pchip->last_bank == pbank->id)    {      pchip->ras_busy += dparam.dtime.r.RC - dparam.dtime.r.PACKET;    }  else    {      pchip->ras_busy += dparam.dtime.r.RR;    }    /* Need precharge */   if ((hit_row == 0) && (pbank->expire > starttime))    {      if (pchip->ras_busy < starttime + dparam.dtime.r.RP)	pchip->ras_busy = starttime + dparam.dtime.r.RP;    }    /*    * Find the earliest free time for CAS/DATA bus. (Figure 19/20)   */  if (pchip->last_type == DRAM_READ && dtrans->is_write)    {      pchip->cas_busy    += dparam.dtime.r.CBUB1;      prdbus->busy_until += dparam.dtime.r.CBUB1;    }  else if (pchip->last_type == DRAM_WRITE &&	   !dtrans->is_write &&	   pchip->last_bank == pbank->id)    {      pchip->cas_busy    += dparam.dtime.r.CBUB2;      prdbus->busy_until += dparam.dtime.r.CBUB2;    }  /* 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -