AbstractMemory * cache_create(ConfigFile *cfg, const char *var_prefix, StatisticsInfo *info, AbstractMemory *mem, Random *rnd) { const char *a = config_file_get(cfg, "associativity"); if (!a) { error_undefined("cache_create", "associativity"); } else if (!strcmp(a, "full")) { return full_cache_create(cfg, var_prefix, info, mem, rnd); } else if (!strcmp(a, "direct")) { return direct_cache_create(cfg, var_prefix, info, mem, rnd); } else { error_invalid("cache_create", "associativity"); } return NULL; }
int config_file_get_int(const ConfigFile *cfg, const char *name, int *p_value) { const char *str = config_file_get(cfg, name); if (!str) { return 0; } char *eptr = NULL; errno = 0; int value = strtol(str, &eptr, 10); if (*eptr || errno) { return -1; } *p_value = value; return 1; }
AbstractMemory * direct_cache_create(ConfigFile *cfg, const char *var_prefix, StatisticsInfo *info, AbstractMemory *mem, Random *rnd) { char buf[124]; DirectCache *c = (DirectCache*) calloc(1, sizeof(*c)); c->b.info = info; const char *strategy = config_file_get(cfg, make_param_name(buf, sizeof(buf), var_prefix, "write_strategy")); if (!strategy) { error_undefined("direct_cache_create", buf); } else if (!strcmp(strategy, "write-through")) { c->b.ops = &direct_cache_wt_ops; c->direct_ops.finalize = direct_cache_wt_finalize; } else if (!strcmp(strategy, "write-back")) { c->b.ops = &direct_cache_wb_ops; c->direct_ops.finalize = direct_cache_wb_finalize; } else { error_invalid("direct_cache_create", buf); } c->mem = mem; // FIXME: реализовать до конца return (AbstractMemory*) c; }
ConfigFile * config_file_parse(const char *path, FILE *log_f) { ConfigFile *cfg = (ConfigFile*) calloc(1, sizeof(*cfg)); cfg->size = 0; cfg->reserved = 10; cfg->params = (struct ConfigParam*) xmalloc( cfg->reserved * sizeof(cfg->params[0])); FILE * fin = fopen(path, "rt"); if (!fin) { fprintf(log_f, "Failed to open %s for reading", path); cfg = config_file_free(cfg); return NULL ; } char buf[LINE_BUF_SIZE]; char key[MAX_LINE_LENGTH + 1]; char value[MAX_LINE_LENGTH + 1]; int lnum = 0; while (fgets(buf, LINE_BUF_SIZE, fin)) { lnum++; int i = 0; int n = strlen(buf); STATE st = STATE_INIT; memset(key, 0, MAX_LINE_LENGTH + 1); memset(value, 0, MAX_LINE_LENGTH + 1); int ks = 0; int vs = 0; for (i = 0; i < n; ++i) { if (buf[i] == '#' && st != STATE_INIT) { break; } switch (st) { case STATE_INIT: if (buf[i] == '#') st = STATE_COMMENT; else if (!isspace(buf[i])) { --i; st = STATE_KEY; } break; case STATE_COMMENT: break; case STATE_KEY: if (buf[i] != '=') { key[ks] = buf[i]; ks++; } else { st = STATE_MIDDLE; } break; case STATE_MIDDLE: if (buf[i] == '=') { fprintf(log_f, "Syntax error in line %d of %s", lnum, path); cfg = config_file_free(cfg); return NULL ; } else if (isspace(buf[i])) { ; // do nothing } else { st = STATE_VALUE; --i; } break; case STATE_VALUE: if (buf[i] == '=') { fprintf(log_f, "Syntax error in line %d of %s", lnum, path); cfg = config_file_free(cfg); return NULL ; } else { value[vs] = buf[i]; vs++; } break; default: break; } } if (st == STATE_VALUE) { if (cfg->size == cfg->reserved) { cfg->reserved *= 2; cfg->params = (ConfigParam *) xrealloc(cfg->params, cfg->reserved * sizeof(cfg->params[0])); } while (key[ks - 1] == '\t' || key[ks - 1] == '\n' || key[ks - 1] == ' ') { --ks; } while (value[vs - 1] == '\t' || value[vs - 1] == '\n' || value[vs - 1] == ' ') { --vs; } key[ks] = 0; value[vs] = 0; if (!IsValidKey(key)) { fprintf(log_f, "Syntax error in line %d of %s", lnum, path); cfg = config_file_free(cfg); return NULL ; } if (config_file_get(cfg, key)) { fprintf(log_f, "Duplicate parameter %s in %s", key, path); cfg = config_file_free(cfg); return NULL ; } cfg->params[cfg->size].name = (char*) xmalloc(ks + 1); cfg->params[cfg->size].value = (char*) xmalloc(vs + 1); strcpy(cfg->params[cfg->size].name, key); strcpy(cfg->params[cfg->size].value, value); cfg->size++; } else if (st == STATE_COMMENT) { // comment } else if (st == STATE_INIT) { // empty line } else { fprintf(log_f, "Syntax error in line %d of %s", lnum, path); cfg = config_file_free(cfg); return NULL ; } } qsort(cfg->params, cfg->size, sizeof(cfg->params[0]), ConfigParam__cmp); fclose(fin); return cfg; }
AbstractMemory * direct_cache_create(ConfigFile *cfg, const char *var_prefix, StatisticsInfo *info, AbstractMemory *mem, Random *rnd) { char buf[1024]; DirectCache *c = (DirectCache*) xcalloc(1, sizeof(*c)); c->b.info = info; const char *strategy = config_file_get(cfg, make_param_name(buf, sizeof(buf), var_prefix, "write_strategy")); if (!strategy) { error_undefined("direct_cache_create", buf); } else if (!strcmp(strategy, "write-through")) { c->b.ops = &direct_cache_wt_ops; c->direct_ops.finalize = direct_cache_wt_finalize; } else if (!strcmp(strategy, "write-back")) { c->b.ops = &direct_cache_wb_ops; c->direct_ops.finalize = direct_cache_wb_finalize; } else { error_invalid("direct_cache_create", buf); } c->mem = mem; int r; r = config_file_get_int(cfg, make_param_name(buf, sizeof(buf), var_prefix, "block_count"), &c->block_count); if (!r) { error_undefined("direct_cache_create", buf); } else if (r < 0) { error_invalid("direct_cache_create", buf); } r = config_file_get_int(cfg, make_param_name(buf, sizeof(buf), var_prefix, "block_size"), &c->block_size); if (!r) { error_undefined("direct_cache_create", buf); } else if (r < 0 || c->block_size <= 0 || c->block_size % 16 != 0 || c->block_size == 0 || c->block_size > 64 || c->block_size == 48) { error_invalid("direct_cache_create", buf); } r = config_file_get_int(cfg, make_param_name(buf, sizeof(buf), var_prefix, "cache_size"), &c->cache_size); if (!r) { error_undefined("direct_cache_create", buf); } else if (r < 0 || c->cache_size <= 0 || c->cache_size > MAX_CACHE_SIZE || c->cache_size % c->block_size != 0) { error_invalid("direct_cache_create", buf); } r = config_file_get_int(cfg, make_param_name(buf, sizeof(buf), var_prefix, "cache_read_time"), &c->cache_read_time); if (!r) { error_undefined("direct_cache_create", buf); } else if (r < 0 || c->cache_read_time <= 0 || c->cache_read_time > MAX_READ_TIME) { error_invalid("direct_cache_create", buf); } r = config_file_get_int(cfg, make_param_name(buf, sizeof(buf), var_prefix, "cache_write_time"), &c->cache_write_time); if (!r) { error_undefined("direct_cache_create", buf); } else if (r < 0 || c->cache_write_time <= 0 || c->cache_write_time > MAX_WRITE_TIME) { error_invalid("direct_cache_create", buf); } c->blocks = (DirectCacheBlock *) xcalloc(1, c->block_count); for (int i = 0; i < c->block_count; ++i) { c->blocks[i].addr = 0; c->blocks[i].dirty = 0; c->blocks[i].mem = (MemoryCell *) xcalloc(1, c->block_size); for (int j = 0; j < c->block_size; ++j) { c->blocks[i].mem[j].flags = 0; c->blocks[i].mem[j].value = 42; } } return (AbstractMemory*) c; }
/*! Создать модель полноассоциативного кеша \param cfg Указатель на структуру, хранящую конфигурационные параметры \param var_prefix Префикс имен параметров \param info Указатель на структуру, хранящую статистику моделирования \return Указатель на структуру описания модели полноассоциативного кеша (в виде указателя на базовую структуру), NULL в случае ошибки */ AbstractMemory * full_cache_create( ConfigFile *cfg, const char *var_prefix, StatisticsInfo *info, AbstractMemory *mem, Random *rnd) { char buf[PARAM_BUF_SIZE]; FullCache *c = (FullCache*) calloc(1, sizeof(*c)); c->b.info = info; c->rnd = rnd; c->mem = mem; c->blocks = NULL; c->block_count = 0; //определяем стратегию записи и соответственно задаём операции: const char fn[] = "full_cache_create"; const char *strategy = config_file_get(cfg, make_param_name(buf, sizeof(buf), var_prefix, "write_strategy")); if (!strategy) { error_undefined(fn, buf); goto full_cache_create_failed; } else if (strcmp(strategy, "write-through") == 0) { c->b.ops = &full_cache_wt_ops; c->full_ops.finalize = full_cache_wt_finalize; } else if (strcmp(strategy, "write-back") == 0) { c->b.ops = &full_cache_wb_ops; c->full_ops.finalize = full_cache_wb_finalize; c->b.info->write_back_needed = 1; } else { error_invalid(fn, buf); goto full_cache_create_failed; } //определяем стратегию замещения и соответственно задаём функцию размещения: strategy = config_file_get(cfg, make_param_name(buf, sizeof(buf), var_prefix, "replacement_strategy")); if (!strategy) { error_undefined(fn, buf); goto full_cache_create_failed; } else if (strcmp(strategy, "random") == 0) { c->full_ops.cache_place = full_cache_random_place; } else { error_invalid(fn, buf); goto full_cache_create_failed; } // считываем и проверяем параметр block_size: int r = config_file_get_int(cfg, make_param_name(buf, sizeof(buf), var_prefix, "block_size"), &c->block_size); if (!r) { error_undefined(fn, buf); goto full_cache_create_failed; } else if (r < 0 || !is_correct_block_size(c->block_size)) { error_invalid(fn, buf); goto full_cache_create_failed; } // считываем и проверяем параметр cache_size: r = config_file_get_int(cfg, make_param_name(buf, sizeof(buf), var_prefix, "cache_size"), &c->cache_size); if (!r) { error_undefined(fn, buf); goto full_cache_create_failed; } else if (r < 0 || c->cache_size <= 0 || c->cache_size > MAX_CACHE_SIZE || c->cache_size % c->block_size != 0) { error_invalid(fn, buf); goto full_cache_create_failed; } // считываем и проверяем параметр cache_read_time: r = config_file_get_int(cfg, make_param_name(buf, sizeof(buf), var_prefix, "cache_read_time"), &c->cache_read_time); if (!r) { error_undefined(fn, buf); goto full_cache_create_failed; } else if (r < 0 || c->cache_read_time <= 0 || c->cache_read_time > MAX_READ_TIME) { error_invalid(fn, buf); goto full_cache_create_failed; } // считываем и проверяем параметр cache_write_time: r = config_file_get_int(cfg, make_param_name(buf, sizeof(buf), var_prefix, "cache_write_time"), &c->cache_write_time); if (!r) { error_undefined(fn, buf); goto full_cache_create_failed; } else if (r < 0 || c->cache_write_time <= 0 || c->cache_write_time > MAX_WRITE_TIME) { error_invalid(fn, buf); goto full_cache_create_failed; } //выделяем блоки кэша: c->block_count = c->cache_size / c->block_size; c->blocks = calloc(c->block_count, sizeof(*c->blocks)); for (int i = 0; i < c->block_count; i++) { c->blocks[i].addr = NO_BLOCK; c->blocks[i].mem = calloc(c->block_size, sizeof(c->blocks[i].mem[0])); } return (AbstractMemory*) c; full_cache_create_failed: return full_cache_free((AbstractMemory*) c); }