📄 bus.c
字号:
} schedule_event(pbus->issuer, pbus->busy_until); if ((req->type == REQUEST) || (req->type == COHE_REPLY)) pbus->num_subtrans[req->src_proc][req->req_type]++; if (req->type == REPLY) { pbus->num_subtrans[req->dest_proc][req->req_type]++; pbus->num_trans[req->dest_proc][req->type]++; pbus->lat_trans[req->dest_proc][req->type]+=req->bus_cycles; } else { pbus->num_trans[req->src_proc][req->type]++; pbus->lat_trans[req->src_proc][req->type]+=req->bus_cycles; }} /*============================================================================= * Send request on the bus (and of transaction). */void Bus_issuer(void){ BUS *pbus = (BUS *) YS__ActEvnt->uptr1; REQ *req = pbus->cur_req; if (req == NULL) YS__errmsg(pbus->nodeid, "Bus_issuer(): Nothing to be sent on bus, why are we here?"); pbus->arb_delay += (YS__Simtime - req->bus_cycles*BUS_FREQUENCY - req->arb_start_time); /*-------------------------------------------------------------------------*/ Bus_finish_trans(pbus, pbus->cur_req); pbus->cur_req = NULL;}/*============================================================================= * Send request on the bus. */void Bus_perform(void){ BUS *pbus = (BUS *) YS__ActEvnt->uptr1; if (pbus->cur_req == NULL) YS__errmsg(pbus->nodeid, "Bus_perform(): Nothing to be sent on bus, why are we here?"); if (pbus->cur_req_owner == PROCESSOR) Cache_send_on_bus(pbus->cur_req); if (pbus->cur_req_owner == IO_MODULE) IO_send_on_bus(pbus->cur_req); if (pbus->cur_req_owner == COORDINATOR) MMC_send_on_bus(pbus->cur_req);}/*============================================================================= * Send an I/O request to the specified I/O port. */void Bus_send_IO_request(REQ *req){ int n; REQ *new_req; if (req->dest_proc < ARCH_cpus) { if (req->dest_proc == TARGET_ALL_CPUS) { /* @@@ copy instance and code @@@ */ for (n = 0; n < ARCH_cpus - 1; n++) { new_req = (REQ*)YS__PoolGetObj(&YS__ReqPool); memcpy(new_req, req, sizeof(REQ)); new_req->dest_proc = n; Cache_get_noncoh_request(new_req); } req->dest_proc = n; Cache_get_noncoh_request(req); } else Cache_get_noncoh_request(req); } else IO_get_request(PID2IO(req->node, req->dest_proc), req);}/*============================================================================= * Send a coherence request on bus. The coherence request will be taken * as external request by each bus module. */void Bus_send_request(REQ *req){ BUS *pbus = PID2BUS(req->node); int n; if (!tlb_non_coh(req->memattributes)) { Cache_get_cohe_request(req); IO_get_cohe_request(req); } MMC_recv_request(req);}/*============================================================================= * Send a coherence request on bus. The coherence request will be taken * as external request by each bus module. */void Bus_send_writepurge(REQ *req){ BUS *pbus = PID2BUS(req->node); int n; if (!tlb_non_coh(req->memattributes)) { Cache_get_cohe_request(req); IO_get_cohe_request(req); } MMC_recv_request(req);}/*============================================================================= * Send a reply for an uncached (I/O) read back to the requester. */void Bus_send_IO_reply(REQ *req){ Cache_get_IO_reply(req);}/*============================================================================= * Send a reply back to the requestor. Used by the coordinator (i.e. * the main memory controller. */void Bus_send_reply(REQ *req){ BUS *pbus = PID2BUS(req->node); req->cohe_done = 1; req->data_done = 1; if (req->src_proc < ARCH_cpus) Cache_get_reply(req); else IO_get_reply(req);}/*============================================================================= * Send a write back to the memory. Used by the processor when * dirty data is casted out the cache. */void Bus_send_writeback(REQ *req){ BUS *pbus = PID2BUS(req->node); MMC_recv_write(req);}/*============================================================================= * Send a coherence report to cluster coordinator. Since there are dedicated * lines between processor and cluster coordinator, a processor can send * the coherence response at any time. */void Bus_send_cohe_response(REQ *req, int state){ MMC_recv_cohe_response(req, state);}/*============================================================================= * Send a coherence data response. It's used to send out dirty data * directly to the requester and the coordinator. */void Bus_send_cohe_data_response(REQ *req){ BUS *pbus = PID2BUS(req->node); REQ *nreq; /* * First, send dirty data to the requester. * Second, send dirty data to the main memory controller. Dirty * data is written back to memory so that the requester can mark * the data clean instead of dirty to avoid further writebacks. */ nreq = (REQ *)YS__PoolGetObj(&YS__ReqPool); memcpy(nreq, req, sizeof(REQ)); if (req->dest_proc < ARCH_cpus) Cache_get_data_response(req); else IO_get_data_response(req); MMC_recv_data_response(nreq);}/*============================================================================= * Send a coherence completion. Used by the coordinator to complete * a request which has got the required data through cache-to-cache * transfer. */void Bus_send_cohe_completion(REQ *req){ req->cohe_done = 1; if (req->src_proc < ARCH_cpus) Cache_get_reply(req); else IO_get_reply(req);}void Bus_start_trans(BUS* pbus, REQ* req){ unsigned mask; if (pbus->busfile == NULL) return; if ((req->req_type != WRITE_UC) && (req->req_type != READ_UC) && (req->req_type != SWAP_UC) && (req->req_type != REPLY_UC)) mask = ~(ARCH_linesz2 - 1); else mask = 0xFFFFFFFF; fprintf(pbus->busfile, "%8.0f Start ", YS__Simtime); if ((req->type == REQUEST) || (req->type == COHE_REPLY)) { fprintf(pbus->busfile, "%s\t%08X\t%2d\t%i -> ", ReqName[req->req_type], req->paddr & mask, req->bus_cycles, req->src_proc); if (req->dest_proc == TARGET_ALL_CPUS) fprintf(pbus->busfile, "All CPUs\n"); if (req->dest_proc == TARGET_ALL_IOS) fprintf(pbus->busfile, "All IOs\n"); if (req->dest_proc == TARGET_ALL_MODULES) fprintf(pbus->busfile, "All Modules\n"); if (req->dest_proc >= 0) fprintf(pbus->busfile, "%i\n", req->dest_proc); } if (req->type == WRITEBACK) fprintf(pbus->busfile, "WRITE_BACK\t%08X\t%2d\t%i -> %i\n", req->paddr & mask, req->bus_cycles, req->src_proc, req->dest_proc); if (req->type == WRITEPURGE) fprintf(pbus->busfile, "WRITE_PURGE\t%08X\t%2d\t%i -> %i\n", req->paddr & mask, req->bus_cycles, req->src_proc, req->dest_proc); if (req->type == REPLY) { fprintf(pbus->busfile, "%s\t%08X\t%2d\t%i -> ", ReqName[req->req_type], req->paddr & mask, req->bus_cycles, req->dest_proc); if (req->src_proc == TARGET_ALL_CPUS) fprintf(pbus->busfile, "All CPUs\n"); if (req->src_proc == TARGET_ALL_IOS) fprintf(pbus->busfile, "All IOs\n"); if (req->src_proc == TARGET_ALL_MODULES) fprintf(pbus->busfile, "All Modules\n"); if (req->src_proc >= 0) fprintf(pbus->busfile, "%i\n", req->src_proc); } fflush(pbus->busfile);}void Bus_finish_trans(BUS* pbus, REQ* req){ if (pbus->busfile == NULL) return; if (req->type == WRITEBACK) fprintf(pbus->busfile, "%8.0f Finish WRITE_BACK\n\n", YS__Simtime); else if (req->type == WRITEPURGE) fprintf(pbus->busfile, "%8.0f Finish WRITE_PURGE\n\n", YS__Simtime); else fprintf(pbus->busfile, "%8.0f Finish %s\n\n", YS__Simtime, ReqName[req->req_type]); fflush(pbus->busfile);}/*****************************************************************************//* Bus statistics functions *//*****************************************************************************/void Bus_print_params(int nid){ YS__statmsg(nid, "Bus Configuration\n"); YS__statmsg(nid, " width: %3d bytes\n", BUS_WIDTH); YS__statmsg(nid, " frequency: %3d (%.3f MHz)\n", BUS_FREQUENCY, 1000000.0 / ((double)CPU_CLK_PERIOD * (double)BUS_FREQUENCY)); YS__statmsg(nid, " arbitration delay: %3d turnaround cycles: %3d\n", BUS_ARBDELAY, BUS_TURNAROUND); YS__statmsg(nid, " mininum delay: %3d (# cycles between addresses)\n", BUS_MINDELAY); YS__statmsg(nid, " outstanding requests: %3d; %d per CPU; %d per I/O device\n", BUS_TOTAL_REQUESTS, BUS_CPU_REQUESTS, BUS_IO_REQUESTS); YS__statmsg(nid, " critical-word first : %s\n", BUS_CRITICAL_WORD ? "on" : "off"); YS__statmsg(nid, "\n");}void Bus_stat_report(int nid){ BUS *pbus = PID2BUS(nid); int n, i; long long num_trans = 0; long long lat_trans = 0; double total_cycles = (YS__Simtime - pbus->last_clear) / BUS_FREQUENCY; YS__statmsg(nid, "Bus Statistics\n"); for (n = 0; n < NUM_MODULES+1; n++) { for (i = 0; i < sizeof(trans_count_t) / sizeof(long long); i++) { num_trans += pbus->num_trans[n][i]; lat_trans += pbus->lat_trans[n][i]; } } YS__statmsg(nid, " Avg. Arbitration Delay: %.2f processor cycles\n\n", pbus->arb_delay / num_trans); YS__statmsg(nid, " Transaction Breakdown\t Count\t Cycles (utilization)\n"); YS__statmsg(nid, " Total\t\t%12lld\t%12lld (%2.2lf%%)\n", num_trans, lat_trans, 100.0 * ((double)lat_trans/total_cycles)); for (i = 0; i < sizeof(trans_count_t) / sizeof(long long); i++) { num_trans = 0; lat_trans = 0; for (n = 0; n < NUM_MODULES+1; n++) { num_trans += pbus->num_trans[n][i]; lat_trans += pbus->lat_trans[n][i]; } if (num_trans == 0) continue; YS__statmsg(nid, " %s \t\t%12lld\t%12lld (%2.2lf%%)\n", RName[i], num_trans, lat_trans, 100.0 * ((double)lat_trans/total_cycles)); for (n = 0; n < NUM_MODULES+1; n++) if (pbus->num_trans[n][i] != 0) { if (n < ARCH_cpus) YS__statmsg(nid, " CPU %i \t\t\t%12lld\n", n, pbus->num_trans[n][i]); else if (n < ARCH_cpus + ARCH_ios) YS__statmsg(nid, " IO %i \t\t\t%12lld\n", n - ARCH_cpus, pbus->num_trans[n][i]); else YS__statmsg(nid, " MemCntl \t\t\t%12lld\n", pbus->num_trans[n][i]); } } YS__statmsg(nid, "\n Transaction Subtype Breakdown\n"); for (i = 0; i < sizeof(subtrans_count_t) / sizeof(long long); i++) { num_trans = 0; for (n = 0; n < NUM_MODULES+1; n++) num_trans += pbus->num_subtrans[n][i]; if (num_trans == 0) continue; YS__statmsg(nid, " %s \t%12lld\n", ReqName[i], num_trans); for (n = 0; n < NUM_MODULES+1; n++) if (pbus->num_subtrans[n][i] != 0) { if (n < ARCH_cpus) YS__statmsg(nid, " CPU %i \t\t\t%12lld\n", n, pbus->num_subtrans[n][i]); else if (n < ARCH_cpus + ARCH_ios) YS__statmsg(nid, " IO %i \t\t\t%12lld\n", n - ARCH_cpus, pbus->num_subtrans[n][i]); else YS__statmsg(nid, " MemCntl \t\t\t%12lld\n", pbus->num_subtrans[n][i]); } } YS__statmsg(nid, "\n\n");}void Bus_stat_clear(int nid){ int i, n; BUS *pbus = PID2BUS(nid); for (n = 0; n < NUM_MODULES+1; n++) { for (i = 0; i < sizeof(trans_count_t) / sizeof(long long); i++) { pbus->num_trans[n][i] = 0; pbus->lat_trans[n][i] = 0; } for (i = 0; i < sizeof(subtrans_count_t) / sizeof(long long); i++) pbus->num_subtrans[n][i] = 0; } pbus->arb_delay = 0.0; pbus->last_clear = YS__Simtime;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -