📄 io_generic.c
字号:
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 + -