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

📄 io_generic.c

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
      if (pio->write_func)	rc = pio->write_func(req);      if (rc)	{	  /* return instances to CPU and free request objects ---------------*/	  creq = req;	  while (creq)	    {	      nreq = creq->parent;	      if ((req->req_type != WRITE_UC) ||		  (!tlb_uc_csb(req->memattributes)))		req->complete(creq, req->hit_type);	      YS__PoolReturnObj(&YS__ReqPool, creq);	      creq = nreq;	    }	}    }    /*-------------------------------------------------------------------------*/  if ((req != NULL) && (req->type == REQUEST) && (req->prcr_req_type == READ))    {      creq = req;      while (creq)	{	  req->perform(creq);	  creq = creq->parent;	}      rc = 1;      if (pio->read_func)	rc = pio->read_func(req);      /* perform read, but only if no read callback is registered */      if (!pio->read_func)	{	  req->type = REPLY;	  req->req_type = REPLY_UC;	  IO_start_transaction(pio, req);	}    }  /*-------------------------------------------------------------------------*/  if ((req != NULL) && (req->type == REQUEST) && (req->prcr_req_type == RMW))    {      creq = req->parent;      while (creq)	{	  creq->perform(creq);	  creq = creq->parent;	}      rc = 1;      if (pio->write_func)	rc = pio->write_func(req);      /* perform write, but only if no read callback is registered */      if (!pio->write_func)	{	  req->type = REPLY;	  req->req_type = REPLY_UC;	  IO_start_transaction(pio, req);	}    }  if ((req != NULL) && rc)    lqueue_remove(&(pio->inqueue));  /*-------------------------------------------------------------------------*/  GetPipeElt(req, pio->inpipe);  if (req)    {      ClearPipeElt(pio->inpipe);      lqueue_add(&(pio->inqueue), req, pio->nodeid);    }  if ((!lqueue_empty(&(pio->inqueue))) ||      (!lqueue_empty(&(pio->cohqueue))) ||      (!PipeEmpty(pio->inpipe)))    schedule_event(pio->inq_event, YS__Simtime + BUS_FREQUENCY);}/*===========================================================================*//* Called by I/O module to issue a bus transaction. Request is inserted      *//* into the delay pipeline. Schedules the output routine if either pipeline  *//* or output queue are not empty.                                            *//*===========================================================================*/int IO_start_transaction(IO_GENERIC *pio, REQ *req){  if (!AddToPipe(pio->outpipe, req))    return(0);  if (IsNotScheduled(pio->outq_event))    schedule_event(pio->outq_event, YS__Simtime + (double)BUS_FREQUENCY);  return(1);}/*===========================================================================*//* Called when output pipeline or queues are not empty. Try to send request  *//* from output queue to the bus interface, remove it from the queue only     *//* if request has been processed (is issued to bus, or has arbitrated, or    *//* is in the arb-waiters queue). Then, move entry from delay pipeline into   *//* host-side output queue, move entry from device-side output queue to delay *//* pipeline, and reschedule itself if either pipeline of queues are not      *//* empty.                                                                    *//*===========================================================================*/void IO_handle_outqueue(void){  REQ        *req;  IO_GENERIC *pio = &(IOs[(int)EventGetArg(NULL)]);  int         index;  /*-------------------------------------------------------------------------*/  req = pio->writebacks;  if (req != NULL)    {      if (IO_start_send_to_bus(pio, req))	{	  pio->writebacks = req->dnext;	  req->dnext = NULL;	}    }    /*-------------------------------------------------------------------------*/  /* take entry off host-side output queue and send to bus interface         */  req = (REQ *)lqueue_head(&pio->outqueue);  if (req)    {      if (IO_start_send_to_bus(pio, req))	lqueue_remove(&(pio->outqueue));    }    /*-------------------------------------------------------------------------*/  /* take entry off pipeline and enter into host-side output queue           */    GetPipeElt(req, pio->outpipe);  if ((req != NULL) && (!lqueue_full(&(pio->outqueue))))    {      ClearPipeElt(pio->outpipe);      lqueue_add(&(pio->outqueue), req, pio->nodeid);    }  /*-------------------------------------------------------------------------*/    if (((!lqueue_empty(&(pio->outqueue))) ||       (!PipeEmpty(pio->outpipe))) &&      IsNotScheduled(pio->outq_event))    schedule_event(pio->outq_event, YS__Simtime + BUS_FREQUENCY);  }/*===========================================================================*//* Attempt to issue transaction on the bus. Initialize various request       *//* fields and try to get a request number if necessary. Enqueue the request  *//* in the arb-waiters queue if other requests are already waiting, or start  *//* the transaction immediately if we own the bus and it is idle. Otherwise,  *//* arbitrate for the bus.                                                    *//*===========================================================================*/int IO_start_send_to_bus(IO_GENERIC *pio, REQ *req){  req->memattributes = 0;  switch (req->type)    {    case REQUEST:      if ((req->req_type == READ_UC) ||	  (req->req_type == WRITE_UC) ||	  (req->req_type == SWAP_UC))	{	  req->bus_start_time = YS__Simtime;	  if ((req->req_type == WRITE_UC) || (req->req_type == SWAP_UC))	    req->bus_cycles = 1 + (req->size + BUS_WIDTH - 1) / BUS_WIDTH;	  else	    req->bus_cycles = 1;	  if ((req->req_type == READ_UC) || (req->req_type == SWAP_UC))	    req->data_done = 0;	}      else	{          req->data_done  = 0;          req->cohe_done  = 0;          req->bus_cycles = 1;          req->bus_start_time = YS__Simtime;        }      break;    case COHE_REPLY:      /*       * Cohe check hit a private dirty line. Send the dirty data to the        * requestor and main memory through cache-to-cache transaction.        */      req->bus_cycles   = ARCH_linesz2 / BUS_WIDTH;      break;    case WRITEBACK:      req->bus_cycles = 1 + ARCH_linesz2 / BUS_WIDTH;      req->parent     = 0;      break;          case WRITEPURGE:      req->bus_cycles = 1 + ARCH_linesz2 / BUS_WIDTH;      req->parent     = 0;      req->data_done  = 1;      req->cohe_done  = 0;            break;          case REPLY:      if (req->req_type == REPLY_UC)	req->bus_cycles = (req->size + BUS_WIDTH - 1) / BUS_WIDTH;      else	req->bus_cycles = ARCH_linesz2 / BUS_WIDTH;      break;    }    return(IO_arb_for_bus(req));}/*===========================================================================*/int IO_arb_for_bus(REQ *req){  IO_GENERIC *pio;  BUS        *pbus = PID2BUS(req->node);  REQ        *oreq;  if (req->type != REPLY)    pio  = PID2IO(req->node, req->src_proc);  else    pio  = PID2IO(req->node, req->dest_proc);  if (pio->arbwaiters_count > 0)    {      oreq = pbus->arbwaiters[req->src_proc].req;      if (lqueue_full(&(pio->arbwaiters)))	return(0);            /* C2C-copies bypass stalled arbitration requests to avoid deadlocks */      if ((req->type == COHE_REPLY) && (oreq != NULL))        {          lqueue_add_head(&(pio->arbwaiters), oreq, pio->nodeid);          pbus->arbwaiters[req->src_proc].req = req;        }      else        {          lqueue_add(&(pio->arbwaiters), req, pio->nodeid);        }      pio->arbwaiters_count++;      return(1);    }    if (InMasterState(pio->nodeid, pio->mid) &&      BusIsIdleUntil(req->bus_cycles * BUS_FREQUENCY))    {      /*      if ((req->type == REQUEST) &&	  (req->req_type != WRITE_UC))	  PID2BUS(req->node)->req_count++;            if ((req->type == REPLY) ||	  (req->type == COHE_REPLY))	PID2BUS(req->node)->req_count--;      */      req->arb_start_time = YS__Simtime;                  IO_in_master_state(req);      return(1);    }    pio->arbwaiters_count++;  Bus_recv_arb_req(pio->nodeid, pio->mid, req, YS__Simtime);  return(1);}/*===========================================================================*//* Start driving the bus to send out the pending request.                    *//* Called by bus module. If more requests are waiting to arbitrate, get a    *//* request from the arb-waiters queue and let it arbitrate.                  *//*===========================================================================*/void IO_in_master_state(REQ *req){  IO_GENERIC *pio;  if (req->type != REPLY)    pio  = PID2IO(req->node, req->src_proc);  else    pio  = PID2IO(req->node, req->dest_proc);  Bus_start(req, IO_MODULE);  /*-------------------------------------------------------------------------*/  if ((req->type == WRITEBACK) || (req->type == COHE_REPLY))    IO_scoreboard_remove(pio, req);  /* More arbitration waiters? ----------------------------------------------*/  if (pio->arbwaiters_count > 0)    {      if (--pio->arbwaiters_count > 0)        {          REQ *newreq;          lqueue_get(&(pio->arbwaiters), newreq);          Bus_recv_arb_req(pio->nodeid, pio->mid, newreq, YS__Simtime);        }    }}/*===========================================================================*//* Send reply back to requestor, called by bus module at end of transaction. *//*===========================================================================*/

⌨️ 快捷键说明

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