mems_disksim.c

来自「disksim是一个非常优秀的磁盘仿真工具」· C语言 代码 · 共 1,418 行 · 第 1/3 页

C
1,418
字号
/* * 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. * *//* mems_disksim.c * * Functions integrating the memsdevice simulator with disksim. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "mems_global.h"#include "mems_internals.h"#include "mems_mapping.h"#include "disksim_ioqueue.h"	/* Provides ioqueue_cleanstats() */#include "disksim_bus.h"	/* Provides bus_get_transfer_time() */#include "config.h"#include "modules/modules.h"/* read-only global vars used during mems_statinit */static char *statdesc_request_energy_uj = "Per-request energy (uJ)";static char *statdesc_seek_time		= "Seek time";static char *statdesc_x_seek_time	= "X Seek time";static char *statdesc_y_seek_time	= "Y Seek time";static char *statdesc_turnaround_time	= "Initial turnaround time";static char *statdesc_turnaround_number	= "Initial turnaround number";static char *statdesc_stream_turnaround_time   = "Streaming turnaround time";static char *statdesc_stream_turnaround_number = "Streaming turnaround number";static char *statdesc_subtrack_accesses = "Subtrack accesses";static char *statdesc_tips_per_access   = "Average tips per access";static char *statdesc_inactive_time	= "Inactive time";static char *statdesc_prefetched_blocks = "Prefetched blocks";struct device_header mems_hdr_initializer;/************************************************************************ * Functions related to mapping physical organization ************************************************************************//* Return the inbus number for the device */intmems_get_busno (ioreq_event *curr){  mems_t *dev = getmems(curr->devno);  intchar busno;  int depth;  busno.value = curr->busno;  depth = dev->depth[0];	/* Only one bus connection allowed */  return busno.byte[depth];}/* How far down the bus hierarchy is this device? */intmems_get_depth (int devno){  mems_t *dev = getmems(devno);  return dev->depth[0];		/* Only one bus connection allowed */}/* Which inbus connects to the device? */intmems_get_inbus (int devno){  mems_t *dev = getmems(devno);  return dev->inbuses[0];	/* Only one bus connection allowed */}/* In which slot on the bus is the device attached? */intmems_get_slotno (int devno){  mems_t *dev = getmems(devno);  return dev->slotno[0];}/* Set the inbus information (where, which slot, how deep) */intmems_set_depth (int devno, int inbusno, int depth, int slotno){  mems_t *dev = getmems(devno);  int count;  count = dev->numinbuses;  dev->numinbuses++;  if ((count + 1) > MAXINBUSES) {    fprintf(stderr,"Too many inbuses specified for memsdevice %d--%d\n", devno, count + 1);    exit(1);  }  dev->inbuses[count] = inbusno;  dev->depth  [count] = depth;  dev->slotno [count] = slotno;  return 0;}/************************************************************************ * ioqueue support functions ************************************************************************//* Get the number of sectors per cylinder */intmems_get_avg_sectpercyl (int devno){  mems_t *dev = getmems(devno);  return mems_get_blocks_per_cylinder(&dev->sled[0]);}/* Find the cylinder, surface, and block mapping of a block */voidmems_get_mapping (int maptype, int devno, int blkno, 		   int *cylptr, int *surfaceptr, int *blkptr){  mems_t *dev = getmems(devno);  mems_sled_t *sled = mems_lbn_to_sled(dev, blkno);  tipsector_coord_set_t up, dn;  tipset_t tipset;  if ((blkno < 0) || (blkno >= dev->numblocks)) {    fprintf(stderr, "Invalid blkno at mems_get_mapping (%d)\n", blkno);    exit(1);  }  mems_lbn_to_position(blkno, sled, &up, &dn, &tipset, cylptr, surfaceptr, blkptr);}/* Get the number of cylinders (e.g., X distance bits) in the device */intmems_get_numcyls (int devno){  mems_t *dev = getmems(devno);  return mems_get_number_of_cylinders(dev);}doublemems_get_acctime (int devno, ioreq_event *req, double maxtime){  // fprintf(stderr, "Entering mems_get_acctime()\n");  /* This function can be extended to calculate the access time   * for any request.  It's not extended yet.  We shouldn't ever   * get here, so just die. */  assert(FALSE);  return 0.0;}double mems_get_seektime (int devno, ioreq_event *req, int checkcache, double maxtime){  mems_t *dev = getmems(req->devno);  mems_sled_t *sled = mems_lbn_to_sled(dev, req->blkno);  double up_time;  double dn_time;  tipsector_coord_set_t up;  tipsector_coord_set_t dn;  tipset_t tipset;  // fprintf(stderr, "Entering mems_get_seektime()\n");  mems_lbn_to_position(req->blkno, sled, &up, &dn, &tipset, NULL, NULL, NULL);  up_time = mems_seek_time(sled, &sled->pos, &up.servo_start, NULL, NULL, NULL, NULL);  dn_time = mems_seek_time(sled, &sled->pos, &dn.servo_start, NULL, NULL, NULL, NULL);  return min(up_time, dn_time);}voidmems_get_average_position (tipsector_coord_set_t *up,			   tipsector_coord_set_t *down,			   coord_t *average){  assert(up->servo_start.x_pos == down->servo_start.x_pos);  average->x_pos = up->servo_start.x_pos;  average->y_pos = (up->servo_start.y_pos + down->servo_start.y_pos) / 2;  average->y_vel = 0;}/* * mems_get_distance * * return the distance from the current position, or a given lbn, to the position *  of req. * * devno - the number of the device in question. * * req - a pointer to the request, which gives the destination position.  we're *       trying to find the distance to this point. * * exact - if equal to -1, then use the sled's current position as the starting *         point.  else, this gives the lbn to use as the starting position. * * direction - ignored for now. * */// #define DISTANCE_DEBUGintmems_get_distance (int devno, ioreq_event *req, int exact, int direction){  coord_t *start_position;  coord_t *dest_position;  mems_t *dev = getmems(devno);  mems_sled_t *sled = mems_lbn_to_sled(dev, req->blkno);  tipsector_coord_set_t up, down;  tipset_t tipset;  int distance1, distance2;  int x1, x2, y1, y2;#ifdef DISTANCE_DEBUG  fprintf(outputfile, "mems_get_distance -- devno = %d, req->blkno = %d, exact = %d, direction = %d\n",	  devno, req->blkno, exact, direction);#endif  if (exact == -1)    {      start_position = mems_get_current_position(sled);    }  else    {      // find the starting position      mems_lbn_to_position(exact,			   sled,			   &up, &down,			   &tipset,			   NULL, NULL, NULL);            start_position = (coord_t *)malloc(sizeof(coord_t));            mems_get_average_position(&up, &down, start_position);    }  // dest_position = (coord_t *)malloc(sizeof(coord_t));    // find the destination position  mems_lbn_to_position(req->blkno,		       sled,		       &up, &down,		       &tipset,		       NULL, NULL, NULL);  // mems_get_average_position(&up, &down, dest_position);  x1 = start_position->x_pos;  x2 = up.servo_start.x_pos;  y1 = start_position->y_pos;  y2 = up.servo_start.y_pos;#ifdef DISTANCE_DEBUG  fprintf(outputfile, "mems_get_distance -- UP - x1 = %d, y1 = %d, x2 = %d, y2 = %d\n",	  x1, y1, x2, y2);#endif  distance1 = (int)(sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));  x1 = start_position->x_pos;  x2 = down.servo_start.x_pos;  y1 = start_position->y_pos;  y2 = down.servo_start.y_pos;#ifdef DISTANCE_DEBUG  fprintf(outputfile, "mems_get_distance -- DOWN - x1 = %d, y1 = %d, x2 = %d, y2 = %d\n",	  x1, y1, x2, y2);#endif  distance2 = (int)(sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));    if (exact != -1)    {      free(start_position);    }#ifdef DISTANCE_DEBUG  fprintf(outputfile, "mems_get_distance -- distance1 = %d, distance2 = %d\n",	  distance1, distance2);#endif  if (distance1 < distance2)    {#ifdef DISTANCE_DEBUG      fprintf(outputfile, "returning distance1 = %d\n", distance1);#endif      return (distance1);    }  else    {#ifdef DISTANCE_DEBUG      fprintf(outputfile, "returning distance2 = %d\n", distance2);#endif      return (distance2);    }}#undef DISTANCE_DEBUGdoublemems_get_servtime (int devno, ioreq_event *req, int checkcache, double maxtime){  // fprintf(stderr, "Entering mems_get_servtime() --");  return mems_get_seektime(devno, req, checkcache, maxtime);}/************************************************************************ * General / informational for disksim components ************************************************************************//* Return the bulk sector transfer time (the greater of the device bulk * sector transfer time and the bus bulk sector transfer time) */doublemems_get_blktranstime (ioreq_event *curr){  mems_t *dev = getmems(curr->devno);  double tmptime;  /* return min(bus_blktranstime,dev_blktranstime) */  tmptime = bus_get_transfer_time(mems_get_busno(curr), 1, (curr->flags & READ));  if (tmptime < dev->blktranstime) {    /* FIXME: Should there be a distinction between read/write times? */    tmptime = dev->blktranstime;  }  return tmptime;}/* What's the maximum number of outstanding requests on the device? */intmems_get_maxoutstanding (int devno){  mems_t *dev = getmems(devno);  return dev->maxqlen;}/* How many blocks are available across all sleds on the device? */intmems_get_number_of_blocks (int devno){  mems_t *dev = getmems(devno);  if (dev->numblocks == 0) mems_check_numblocks(dev);  return dev->numblocks;}/************************************************************************ * Statistics stuff ************************************************************************/static voidmems_statinit (int devno, int firsttime){  mems_t *dev = getmems(devno);  int j;  /* First initialize device statistics */  if (firsttime) {    stat_initialize (statdeffile, statdesc_request_energy_uj, 		     &dev->stat.request_energy_uj);    stat_initialize (statdeffile, statdesc_seek_time,		     &dev->stat.seek_time);    stat_initialize (statdeffile, statdesc_x_seek_time,		     &dev->stat.x_seek_time);    stat_initialize (statdeffile, statdesc_y_seek_time,		     &dev->stat.y_seek_time);    stat_initialize (statdeffile, statdesc_turnaround_time,		     &dev->stat.turnaround_time);    stat_initialize (statdeffile, statdesc_turnaround_number,		     &dev->stat.turnaround_number);    stat_initialize (statdeffile, statdesc_stream_turnaround_time,		     &dev->stat.stream_turnaround_time);    stat_initialize (statdeffile, statdesc_stream_turnaround_number,		     &dev->stat.stream_turnaround_number);    stat_initialize (statdeffile, statdesc_subtrack_accesses,		     &dev->stat.subtrack_accesses);    stat_initialize (statdeffile, statdesc_tips_per_access,		     &dev->stat.tips_per_access);    stat_initialize (statdeffile, statdesc_inactive_time,		     &dev->stat.inactive_time);    stat_initialize (statdeffile, statdesc_prefetched_blocks,		     &dev->stat.prefetched_blocks);  } else {    stat_reset (&dev->stat.request_energy_uj);    stat_reset (&dev->stat.seek_time);    stat_reset (&dev->stat.x_seek_time);    stat_reset (&dev->stat.y_seek_time);    stat_reset (&dev->stat.turnaround_time);    stat_reset (&dev->stat.turnaround_number);    stat_reset (&dev->stat.stream_turnaround_time);    stat_reset (&dev->stat.stream_turnaround_number);    stat_reset (&dev->stat.subtrack_accesses);    stat_reset (&dev->stat.tips_per_access);    stat_reset (&dev->stat.inactive_time);    stat_reset (&dev->stat.prefetched_blocks);  }  dev->stat.total_energy_j = 0.0;  dev->stat.servicing_energy_j = 0.0;  dev->stat.startup_energy_j   = 0.0;  dev->stat.idle_energy_j      = 0.0;  dev->stat.inactive_energy_j  = 0.0;  dev->stat.num_spinups    = 0;  dev->stat.num_spindowns  = 0;  dev->stat.num_buffer_accesses = 0;  dev->stat.num_buffer_hits     = 0;  dev->stat.num_initial_turnarounds = 0;  dev->stat.num_stream_turnarounds  = 0;  /* Now initialize sled statistics */  for (j=0; j < dev->num_sleds; j++) {    if (firsttime) {      stat_initialize (statdeffile, statdesc_request_energy_uj,		       &dev->sled[j].stat.request_energy_uj);      stat_initialize (statdeffile, statdesc_seek_time,		       &dev->sled[j].stat.seek_time);      stat_initialize (statdeffile, statdesc_x_seek_time,		       &dev->sled[j].stat.x_seek_time);      stat_initialize (statdeffile, statdesc_y_seek_time,		       &dev->sled[j].stat.y_seek_time);      stat_initialize (statdeffile, statdesc_turnaround_time,		       &dev->sled[j].stat.turnaround_time);      stat_initialize (statdeffile, statdesc_turnaround_number,		       &dev->sled[j].stat.turnaround_number);      stat_initialize (statdeffile, statdesc_stream_turnaround_time,		       &dev->sled[j].stat.stream_turnaround_time);      stat_initialize (statdeffile, statdesc_stream_turnaround_number,

⌨️ 快捷键说明

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