mems_event.c
来自「disksim是一个非常优秀的磁盘仿真工具」· C语言 代码 · 共 1,946 行 · 第 1/4 页
C
1,946 行
/* * DiskSim Storage Subsystem Simulation Environment (Version 4.0) * Revision Authors: John Bucy, Greg Ganger * Contributors: John Griffin, Jiri Schindler, Steve Schlosser * * Copyright (c) of Carnegie Mellon University, 2001-2008. * * This software is being provided by the copyright holders under the * following license. By obtaining, using and/or copying this software, * you agree that you have read, understood, and will comply with the * following terms and conditions: * * Permission to reproduce, use, and prepare derivative works of this * software is granted provided the copyright and "No Warranty" statements * are included with all reproductions and derivative works and associated * documentation. This software may also be redistributed without charge * provided that the copyright and "No Warranty" statements are included * in all redistributions. * * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS. * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. * COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE * OR DOCUMENTATION. * *//* TODO * * Replace curr->time with simtime? Is this a problem? * Remove lastreq_lbn? */#include <stdio.h>#include <stdlib.h>#include "mems_global.h"#include "mems_disksim.h"#include "mems_mapping.h"#include "mems_internals.h"#include "mems_buffer.h"#include "disksim_bus.h"#include "disksim_ioqueue.h"// #define VERBOSE_EVENTLOOPunsigned int mems_reqinfo_mallocs = 0;unsigned int mems_reqinfo_frees = 0;unsigned int mems_extent_mallocs = 0;unsigned int mems_extent_frees = 0;/************************************************************************ * Bus stuff ************************************************************************/static voidmems_send_event_up_path (ioreq_event * curr, double delay){ /* Acquire the bus (if not already acquired), then use bus_delay * to send the event up the path. */ mems_t *dev = getmems(curr->devno); int busno = mems_get_busno(curr); int slotno = mems_get_slotno(curr->devno); /* Put new request at head of buswait queue */ curr->next = dev->buswait; dev->buswait = curr; curr->tempint1 = busno; curr->time = delay; if (dev->busowned == -1) { /* Must get ownership of bus first */ if (bus_ownership_get(busno, slotno, curr) == FALSE) { /* FIXME: dev->stat.requestedbus = simtime */ } else { bus_delay(busno, DEVICE, curr->devno, delay, curr); } } else if (dev->busowned == busno) { /* Already own the bus, so send it on up! */ bus_delay(busno, DEVICE, curr->devno, delay, curr); } else { fprintf(stderr, "Wrong bus owned for transfer desired!\n"); exit(1); }}voidmems_bus_ownership_grant (int devno, ioreq_event *curr, int busno, double arbdelay){ mems_t *dev = getmems(devno); ioreq_event *tmp = dev->buswait; #ifdef VERBOSE_EVENTLOOP printf("Hi! I'm in mems_bus_ownership_grant: %f\n", simtime); fflush(stdout);#endif while ((tmp != NULL) && (tmp != curr)) tmp = tmp->next; if (!tmp) { fprintf(stderr, "Bus ownership granted to unknown request -- devno %d, busno %d\n", devno, busno); exit(1); } dev->busowned = busno; /* FIXME: Do we _really_ want to keep this statistic? Is it valid? */ // dev->stat.waitingforbus += simtime - dev->stat.requestedbus; // dev->stat.numbuswaits++; bus_delay(busno, DEVICE, dev->devno, tmp->time, curr);}voidmems_bus_delay_complete (int devno, ioreq_event *curr, int sentbusno){ mems_t *dev = getmems(devno); intchar slotno; intchar busno; int depth;#ifdef VERBOSE_EVENTLOOP printf("Hello! I'm in mems_bus_delay_complete: %f\n", simtime); fflush(stdout);#endif busno.value = curr->busno; slotno.value = curr->slotno; depth = mems_get_depth(curr->devno); slotno.byte[depth] = slotno.byte[depth] >> 4; curr->time = (double)0.0; if (curr == dev->buswait) { dev->buswait = curr->next; } else { ioreq_event *tmp = dev->buswait; while ((tmp->next != NULL) && (tmp->next != curr)) tmp = tmp->next; if (tmp->next != curr) { fprintf(stderr, "Bus delay complete for unknown request -- devno %d, busno %d\n", devno, busno.value); exit(1); } } if (depth == 0) { intr_request ((event *)curr); } else { bus_deliver_event (busno.byte[depth], slotno.byte[depth], curr); }}/************************************************************************ * Other support functions ************************************************************************/mems_extent_t *mems_get_new_extent(ioreq_event *curr){ mems_extent_t *new_extent = (mems_extent_t *)malloc(sizeof(mems_extent_t)); // mems_extent_t *new_extent = (mems_extent_t *)getfromextraq(); mems_extent_mallocs++; new_extent->firstblock = curr->blkno; new_extent->lastblock = curr->blkno + curr->bcount - 1; new_extent->completed_block_media = -1; new_extent->completed_block_bus = -1; new_extent->bus_done = FALSE; new_extent->media_done = FALSE; new_extent->next = NULL; new_extent->prev = NULL; new_extent->request = curr; new_extent->next_block_start = -1; new_extent->next_block_end = -1; return new_extent;}voidmems_update_reqinfo(ioreq_event *curr){ mems_reqinfo_t *r = curr->mems_reqinfo; mems_extent_t *extent_ptr = r->extents; ioreq_event *event_ptr; ioreq_event *next_event_ptr;#ifdef VERBOSE_EVENTLOOP printf("mems_update_reqinfo -- entry\n");#endif event_ptr = curr; while(event_ptr) { next_event_ptr = event_ptr->batch_next; free(((mems_reqinfo_t *)event_ptr->mems_reqinfo)->extents); mems_reqinfo_frees++; if (event_ptr->mems_reqinfo != r) { free(event_ptr->mems_reqinfo); mems_reqinfo_frees++; //addtoextraq(event_ptr->mems_reqinfo); } event_ptr = next_event_ptr; } r->extents = mems_get_new_extent(curr); r->num_extents = 1; r->batch_arrival_time = curr->time;#ifdef VERBOSE_EVENTLOOP printf("mems_update_reqinfo -- curr->flags = %d\n", curr->flags);#endif /* if ((curr->flags & 0x1) == DISKSIM_WRITE) {#ifdef VERBOSE_EVENTLOOP printf("mems_update_reqinfo -- this is a write\n");#endif r->extents->completed_block_bus = r->extents->lastblock; r->extents->bus_done = TRUE;#ifdef VERBOSE_EVENTLOOP printf("mems_update_reqinfo -- completed_block_bus = %d\n", r->extents->completed_block_bus);#endif } */ extent_ptr = r->extents; event_ptr = curr->batch_next; while (event_ptr != NULL) { extent_ptr->next = mems_get_new_extent(event_ptr); extent_ptr->next->prev = extent_ptr; if ((event_ptr->flags & 0x1) == DISKSIM_WRITE) {#ifdef VERBOSE_EVENTLOOP printf("mems_update_reqinfo -- this is a write\n");#endif extent_ptr->next->completed_block_bus = extent_ptr->next->lastblock; extent_ptr->next->bus_done = TRUE;#ifdef VERBOSE_EVENTLOOP printf("mems_update_reqinfo -- completed_block_bus = %d\n", extent_ptr->next->completed_block_bus);#endif } r->num_extents++; if (curr->time < r->batch_arrival_time) { r->batch_arrival_time = curr->time; } event_ptr->mems_reqinfo = NULL; event_ptr = event_ptr->batch_next; extent_ptr = extent_ptr->next; }}static mems_reqinfo_t *mems_get_new_reqinfo (ioreq_event *curr){ ioreq_event *event_ptr; mems_extent_t *extent_ptr; // mems_reqinfo_t *r = (mems_reqinfo_t *)getfromextraq(); mems_reqinfo_t *r = (mems_reqinfo_t *)malloc(sizeof(mems_reqinfo_t)); mems_reqinfo_mallocs++; extent_ptr = r->extents; r->extents = mems_get_new_extent(curr); r->num_extents = 1; extent_ptr = r->extents; event_ptr = curr; // if there are more in the batch (there shouldn't be) while (event_ptr->batch_next != NULL) { event_ptr = event_ptr->batch_next; extent_ptr->next = mems_get_new_extent(event_ptr); r->num_extents++; } r->bus_pending = FALSE; r->bus_done = FALSE; r->media_done = FALSE; r->bus_extent = NULL; r->request_energy_uj = 0.0; r->firstseek = 1; /* TRUE: first seek hasn't yet completed */ r->subtrack_access_num = 0; r->subtrack_access_tips = 0; return r;}static struct mems_prefetch_info *mems_get_prefetch_info (ioreq_event *curr){ mems_sled_t *sled = curr->mems_sled; mems_reqinfo_t *reqinfo = curr->mems_reqinfo; struct mems_prefetch_info *p; if (!sled->prefetch_depth) return NULL; p = (struct mems_prefetch_info *)getfromextraq(); p->firstblock = reqinfo->lastblock + 1; p->lastblock = p->firstblock + sled->prefetch_depth - 1; p->completed_block = -1; p->next_block_start = -1; p->next_block_end = -1; return p;}static voidsend_disconnect (ioreq_event *curr, double latency){ ioreq_event *intrp = ioreq_copy(curr); intrp->type = IO_INTERRUPT_ARRIVE; intrp->cause = DISCONNECT; mems_send_event_up_path(intrp, latency);}static voidsend_completion (ioreq_event *curr, double latency){ ioreq_event *intrp = ioreq_copy(curr); intrp->type = IO_INTERRUPT_ARRIVE; intrp->cause = COMPLETION; mems_send_event_up_path(intrp, latency);}static voidsend_reconnect (ioreq_event *curr, double latency){ ioreq_event *intrp = ioreq_copy(curr); intrp->type = IO_INTERRUPT_ARRIVE; intrp->cause = RECONNECT; mems_send_event_up_path(intrp, latency);}static voidmems_request_complete (ioreq_event *curr, double latency){ mems_sled_t *sled = curr->mems_sled; mems_reqinfo_t *reqinfo = curr->mems_reqinfo; ioreq_event *batch_ptr; ioreq_event *next_ptr;#ifdef VERBOSE_EVENTLOOP printf("Entering mems_request_complete() - curr->blkno = %d, time = %f, latency = %f\n", curr->blkno, simtime, latency); fflush(stdout);#endif { /* Verify that we're not insane here */ mems_reqinfo_t *r = curr->mems_reqinfo; // assert ((r->bus_done == TRUE) && (r->media_done == TRUE)); } if (!ioqueue_physical_access_done(sled->queue, curr)) { fprintf(stderr, "mems_request_complete: sled ioreq_event not found by ioqueue_physical_access_done call\n"); exit(1); } /* if (!ioqueue_physical_access_done(sled->dev->queue, curr)) { fprintf(stderr, "mems_request_complete: device ioreq_event not found by ioqueue_physical_access_done call\n"); exit(1); } */ send_completion(curr, latency); if (reqinfo && reqinfo->subtrack_access_num) { /* Don't keep statistics for requests that hit entirely in the buffer * WARNING: If you _want_ to keep these, note that the * stat.tips_per_access statistic will die with a divide-by-zero * error unless you do something else here */ stat_update(&sled->dev->stat.request_energy_uj, reqinfo->request_energy_uj); stat_update(&sled->stat.request_energy_uj, reqinfo->request_energy_uj); stat_update(&sled->dev->stat.subtrack_accesses, reqinfo->subtrack_access_num); stat_update(&sled->stat.subtrack_accesses, reqinfo->subtrack_access_num); stat_update(&sled->dev->stat.tips_per_access, reqinfo->subtrack_access_tips / reqinfo->subtrack_access_num); stat_update(&sled->stat.tips_per_access, reqinfo->subtrack_access_tips / reqinfo->subtrack_access_num); }}voidprint_extent_info(mems_reqinfo_t *reqinfo){ int i; mems_extent_t *extent_ptr; extent_ptr = reqinfo->extents; i = 0; while(extent_ptr != NULL) { printf(" extent %d, firstblock = %d, lastblock = %d\n", i, extent_ptr->firstblock, extent_ptr->lastblock); printf(" next_block_start = %d, next_block_end = %d\n", extent_ptr->next_block_start, extent_ptr->next_block_end); printf(" completed_block_media = %d, completed_block_bus = %d\n", extent_ptr->completed_block_media, extent_ptr->completed_block_bus); printf(" media_done = %d, bus_done = %d\n", extent_ptr->media_done, extent_ptr->bus_done); extent_ptr = extent_ptr->next; i++; }}/************************************************************************ * Energy updating functions ************************************************************************/voidmems_energy_update_device_overhead_complete_inactive(mems_sled_t *sled){ double energy_j; /* Account for both energy consumed during inactive period... */ energy_j = (sled->inactive_power_mw * (simtime - sled->lastreq_comptime)) / 1000000.0; sled->dev->stat.total_energy_j += energy_j; sled->stat.total_energy_j += energy_j; sled->dev->stat.inactive_energy_j += energy_j; sled->stat.inactive_energy_j += energy_j;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?