diff options
Diffstat (limited to 'src/mem/gems_common/ioutil/initvar.cc')
-rw-r--r-- | src/mem/gems_common/ioutil/initvar.cc | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/src/mem/gems_common/ioutil/initvar.cc b/src/mem/gems_common/ioutil/initvar.cc new file mode 100644 index 000000000..62fe3b6af --- /dev/null +++ b/src/mem/gems_common/ioutil/initvar.cc @@ -0,0 +1,585 @@ +/* + * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + This file has been modified by Kevin Moore and Dan Nussbaum of the + Scalable Systems Research Group at Sun Microsystems Laboratories + (http://research.sun.com/scalable/) to support the Adaptive + Transactional Memory Test Platform (ATMTP). + + Please send email to atmtp-interest@sun.com with feedback, questions, or + to request future announcements about ATMTP. + + ---------------------------------------------------------------------- + + File modification date: 2008-02-23 + + ---------------------------------------------------------------------- +*/ + +/* + * FileName: initvar.C + * Synopsis: implementation of global variable initialization in simics + * Author: cmauer + * Version: $Id$ + */ + +/*------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------*/ + +using namespace std; +#include <string> +#include <map> +#include <stdlib.h> + +// Maurice +// extern "C" { +// #include "global.hh" +// #include "simics/api.hh" +// #ifdef SIMICS22X +// #include "configuration_api.hh" +// #endif +// #ifdef SIMICS30 +// #include "configuration.hh" +// #endif +// }; + +#include "mem/ruby/common/Global.hh" + +#include "mem/gems_common/ioutil/confio.hh" +#include "mem/gems_common/ioutil/initvar.hh" + +/*------------------------------------------------------------------------*/ +/* Variable declarations */ +/*------------------------------------------------------------------------*/ + +// define global "constants" using centralized file +#define PARAM( NAME ) \ + int32 NAME; +#define PARAM_UINT( NAME ) \ + uint32 NAME; +#define PARAM_ULONG( NAME ) \ + uint64 NAME; +#define PARAM_BOOL( NAME ) \ + bool NAME; +#define PARAM_DOUBLE( NAME ) \ + double NAME; +#define PARAM_STRING( NAME ) \ + char *NAME; +#define PARAM_ARRAY( PTYPE, NAME, ARRAY_SIZE ) \ + PTYPE NAME[ARRAY_SIZE]; +#include "mem/ruby/config/config.hh" +#undef PARAM +#undef PARAM_UINT +#undef PARAM_ULONG +#undef PARAM_BOOL +#undef PARAM_DOUBLE +#undef PARAM_STRING +#undef PARAM_ARRAY + +/** global initvar object */ +initvar_t *initvar_t::m_inst = NULL; + +/*------------------------------------------------------------------------*/ +/* Forward declarations */ +/*------------------------------------------------------------------------*/ + +static attr_value_t initvar_get_attr( void *ptr, void *obj ); +static set_error_t initvar_set_attr( void *ptr, void *obj, + attr_value_t *value ); + +/*------------------------------------------------------------------------*/ +/* Constructor(s) / destructor */ +/*------------------------------------------------------------------------*/ + +//************************************************************************** +initvar_t::initvar_t( const char *name, const char *relativeIncludePath, + const char *initializingString, + void (*allocate_fn)(void), + void (*my_generate_fn)(void) ) +{ + m_is_init = false; + m_name = (char *) malloc( sizeof(char)*(strlen( name ) + 2) ); + m_rel_include_path = (char *) malloc( sizeof(char)*(strlen( relativeIncludePath ) + 2) ); + m_config_filename = NULL; + strcpy( m_name, name ); + strcpy( m_rel_include_path, relativeIncludePath ); + m_allocate_f = allocate_fn; + m_generate_values_f = my_generate_fn; + + initvar_t::m_inst = this; + init_config_reader( initializingString ); +} + +//************************************************************************** +initvar_t::~initvar_t( ) +{ +#define PARAM( NAME ) +#define PARAM_UINT( NAME ) +#define PARAM_ULONG( NAME ) +#define PARAM_BOOL( NAME ) +#define PARAM_DOUBLE( NAME ) +#define PARAM_STRING( NAME ) \ + if (NAME != NULL) { \ + free( NAME ); \ + NAME = NULL; \ + } +#define PARAM_ARRAY( PTYPE, NAME, ARRAY_SIZE ) +#include "mem/ruby/config/config.hh" +#undef PARAM +#undef PARAM_UINT +#undef PARAM_ULONG +#undef PARAM_BOOL +#undef PARAM_DOUBLE +#undef PARAM_STRING +#undef PARAM_ARRAY + if (m_name) { + free( m_name ); + } + if (m_rel_include_path) { + free( m_rel_include_path ); + } + if (m_config_reader) { + delete m_config_reader; + } + if (m_config_filename) { + delete m_config_filename; + } +} + +//************************************************************************** +void initvar_t::init_config_reader( const char *initString ) +{ + int rc; + const char *name; + + m_config_reader = new confio_t(); + m_config_reader->setVerbosity( false ); + + // Initialize the config reader object to identify each parameter +#define PARAM_UINT PARAM +#define PARAM_ULONG PARAM +#define PARAM_BOOL PARAM +#define PARAM_DOUBLE PARAM +#define PARAM( NAME ) \ + name = #NAME; \ + rc = m_config_reader->register_attribute( name, \ + initvar_get_attr, (void *) name, \ + initvar_set_attr, (void *) name ); +#define PARAM_STRING( NAME ) \ + NAME = NULL; \ + name = #NAME; \ + rc = m_config_reader->register_attribute( name, \ + initvar_get_attr, (void *) name, \ + initvar_set_attr, (void *) name ); +#define PARAM_ARRAY( PTYPE, NAME, ARRAY_SIZE ) \ + name = #NAME; \ + rc = m_config_reader->register_attribute( name, \ + initvar_get_attr, (void *) name, \ + initvar_set_attr, (void *) name ); + +#include "mem/ruby/config/config.hh" +#undef PARAM +#undef PARAM_UINT +#undef PARAM_ULONG +#undef PARAM_BOOL +#undef PARAM_DOUBLE +#undef PARAM_STRING +#undef PARAM_ARRAY + + // read the default configuration from the embedded text file + rc = m_config_reader->readConfigurationString( initString ); + (*m_generate_values_f)(); +} + +/*------------------------------------------------------------------------*/ +/* Public methods */ +/*------------------------------------------------------------------------*/ + +//************************************************************************** +void initvar_t::allocate( void ) +{ + if ( confirm_init() ) { + DEBUG_OUT("error: %s initvar::allocate() called twice\n", m_name); + return; + } + + (*m_generate_values_f)(); + (*m_allocate_f)(); + m_is_init = true; +} + +//************************************************************************** +void initvar_t::checkInitialization( void ) +{ + m_config_reader->checkInitialization(); +} + +//************************************************************************** +int initvar_t::dispatch_get( void *id, void *obj, + attr_value_t *idx ) +{ + const char *command = (const char *) id; + if ( !confirm_init() ) { + DEBUG_OUT("error: %s is uninitialized. unable to get \'%s\'\n", m_name, command); + DEBUG_OUT(" : you must initialize %s with a configuration file first.\n", m_name); + DEBUG_OUT(" : use the command \'%s0.init\'\n", m_name); + + return 0; + } + + std::cerr << __FILE__ << "(" << __LINE__ << "): Not implmented." << std::endl; + return 0; +} + + +//************************************************************************** +set_error_t initvar_t::dispatch_set( void *id, void *obj, + attr_value_t *val, attr_value_t *idx ) +{ + const char *command = (const char *) id; + + // DEBUG_OUT("set attribute: %s\n", command); + if (!strcmp(command, "init")) { + if (val->kind == Sim_Val_String) { + if (!strcmp( val->u.string, "" )) { + // update generated values, then allocate + allocate(); + } else { + read_config( val->u.string ); + allocate(); + } + return Sim_Set_Ok; + } else { + return Sim_Set_Need_String; + } + } else if (!strcmp(command, "readparam")) { + if (val->kind == Sim_Val_String) { + read_config( val->u.string ); + return Sim_Set_Ok; + } else { + return Sim_Set_Need_String; + } + } else if (!strcmp(command, "saveparam")) { + if (val->kind == Sim_Val_String) { + FILE *fp = fopen( val->u.string, "w" ); + if (fp == NULL) { + ERROR_OUT("error: unable to open file: %s\n", val->u.string); + return Sim_Set_Illegal_Value; + } + list_param( fp ); + if (fp != NULL) { + fclose( fp ); + } + return Sim_Set_Ok; + } else { + ERROR_OUT("error: saveparam given wrong type.\n"); + return Sim_Set_Illegal_Value; + } + } else if (!strcmp(command, "param")) { + if (val->kind == Sim_Val_Integer) { + list_param( stdout ); + return Sim_Set_Ok; + } else if ( val->kind == Sim_Val_List && + val->u.list.size == 2 && + val->u.list.vector[0].kind == Sim_Val_String ) { + return (set_param( val->u.list.vector[0].u.string, + &val->u.list.vector[1] )); + } else { + DEBUG_OUT("error: set parameter given wrong type.\n"); + return Sim_Set_Illegal_Value; + } + } + + if ( !confirm_init() ) { + DEBUG_OUT("error: %s is uninitialized. unable to set \'%s\'\n", m_name, id); + DEBUG_OUT(" : you must initialize %s with a configuration file first.\n", m_name); + DEBUG_OUT(" : use the command \'%s0.init\'\n", m_name); + return Sim_Set_Illegal_Value; + } + + + std::cerr << __FILE__ << "(" << __LINE__ << "): Not implmented." << std::endl; + return Sim_Set_Illegal_Value; +} + +/*------------------------------------------------------------------------*/ +/* Accessor(s) / mutator(s) */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* Private methods */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* Static methods */ +/*------------------------------------------------------------------------*/ + +//************************************************************************** +static attr_value_t initvar_get_attr( void *ptr, void *obj ) +{ + const char *name = (const char *) ptr; + attr_value_t ret; + memset( &ret, 0, sizeof(attr_value_t) ); + +#define PARAM_UINT PARAM +#define PARAM_ULONG PARAM +#define PARAM_BOOL PARAM +#define PARAM( NAME ) \ + if (!strcmp(name, #NAME)) { \ + ret.kind = Sim_Val_Integer; \ + ret.u.integer = NAME; \ + return (ret); \ + } +#define PARAM_DOUBLE( NAME ) \ + if (!strcmp(name, #NAME)) { \ + ret.kind = Sim_Val_Floating; \ + ret.u.floating = NAME; \ + return (ret); \ + } +#define PARAM_STRING( NAME ) \ + if (!strcmp(name, #NAME)) { \ + ret.kind = Sim_Val_String; \ + ret.u.string = NAME; \ + return (ret); \ + } +#define PARAM_ARRAY( PTYPE, NAME, ARRAY_SIZE ) \ + if (!strcmp(name, #NAME)) { \ + ret.kind = Sim_Val_List; \ + ret.u.list.size = ARRAY_SIZE; \ + ret.u.list.vector = mallocAttribute( ARRAY_SIZE ); \ + for (int i = 0; i < ARRAY_SIZE; i++) { \ + ret.u.list.vector[i].u.integer = NAME[i]; \ + } \ + return (ret); \ + } + +#include "mem/ruby/config/config.hh" +#undef PARAM +#undef PARAM_UINT +#undef PARAM_ULONG +#undef PARAM_BOOL +#undef PARAM_DOUBLE +#undef PARAM_STRING +#undef PARAM_ARRAY + + DEBUG_OUT("error: %s not found.\n", name); + ret.kind = Sim_Val_Invalid; + return (ret); +} + +//*************************************************************************** +static set_error_t initvar_set_attr( void *ptr, void *obj, + attr_value_t *value ) +{ + const char *name = (const char *) ptr; + +#define PARAM_UINT PARAM +#define PARAM_ULONG PARAM +#define PARAM( NAME ) \ + if (!strcmp(name, #NAME)) { \ + if ( value->kind != Sim_Val_Integer ) { \ + ERROR_OUT("error: %s is not an integer\n", name );\ + return Sim_Set_Need_Integer; \ + } \ + NAME = value->u.integer; \ + return Sim_Set_Ok; \ + } +#define PARAM_BOOL( NAME ) \ + if (!strcmp(name, #NAME)) { \ + if ( value->kind != Sim_Val_String ) { \ + ERROR_OUT("error: %s is not an bool string\n", name );\ + return Sim_Set_Need_String; \ + } \ + if (!strcmp(value->u.string, "true")) { \ + NAME = true; \ + } else if (!strcmp(value->u.string, "false")) { \ + NAME = false; \ + } else { \ + ERROR_OUT("error: value %s for %s is not an bool string (set to false)\n", value->u.string, name );\ + NAME = false; \ + } \ + return Sim_Set_Ok; \ + } +#define PARAM_DOUBLE( NAME ) \ + if (!strcmp(name, #NAME)) { \ + if ( value->kind != Sim_Val_String ) { \ + ERROR_OUT("error: %s is not a float\n", name );\ + return Sim_Set_Need_Floating; \ + } \ + NAME = atof( value->u.string ); \ + return Sim_Set_Ok; \ + } +#define PARAM_STRING( NAME ) \ + if (!strcmp(name, #NAME)) { \ + if ( value->kind != Sim_Val_String ) { \ + ERROR_OUT("error: %s is not an string\n", name ); \ + return Sim_Set_Need_String; \ + } \ + if (NAME != NULL) { \ + free( NAME ); \ + } \ + NAME = strdup( value->u.string ); \ + return Sim_Set_Ok; \ + } +#define PARAM_ARRAY( PTYPE, NAME, ARRAY_SIZE ) \ + if (!strcmp(name, #NAME)) { \ + if ( value->kind != Sim_Val_List ) { \ + ERROR_OUT("error: %s is not an list\n", name ); \ + return Sim_Set_Need_List; \ + } \ + if ( value->u.list.size != ARRAY_SIZE ) { \ + ERROR_OUT("error: %s has %lld elements (should be %d)\n", name, value->u.list.size, ARRAY_SIZE); \ + return Sim_Set_Illegal_Value; \ + } \ + for (int i = 0; i < ARRAY_SIZE; i++) { \ + NAME[i] = value->u.list.vector[i].u.integer; \ + } \ + return Sim_Set_Ok; \ + } + +#include "mem/ruby/config/config.hh" +#undef PARAM +#undef PARAM_UINT +#undef PARAM_ULONG +#undef PARAM_BOOL +#undef PARAM_DOUBLE +#undef PARAM_STRING +#undef PARAM_ARRAY + + ERROR_OUT("error: %s not a parameter\n", name); + return Sim_Set_Illegal_Value; +} + +//*************************************************************************** +void initvar_t::read_config( const char *parameterFile ) +{ + DEBUG_OUT("read configuration: %s\n", parameterFile ); + m_config_filename = strdup( parameterFile ); + int rc = m_config_reader->readConfiguration( parameterFile, + m_rel_include_path ); + if ( rc < 0 ) { + ERROR_OUT("fatal error in read configuration: unable to continue.\n"); + exit(1); + } + // update generated values + (*m_generate_values_f)(); +} + +/** sets one of the parameters */ +//************************************************************************** +set_error_t initvar_t::set_param( const char *name, attr_value_t *value ) +{ + + // [dann 2007-04-04] ATMTP VV + // + // HACK ALERT: allow setting REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH, + // PROFILE_EXCEPTIONS, PROFILE_XACT, ATMTP_DEBUG_LEVEL and + // ATMTP_ENABLED after initialization. This works is because ruby's + // m_generate_values_f() does nothing -- more particularly, nothing + // that depends on any of these parameters is pre-calculated + // anywhere. + // + if (strcmp(name, "REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH") != 0 && + strcmp(name, "PROFILE_EXCEPTIONS") != 0 && + strcmp(name, "PROFILE_XACT") != 0 && + strcmp(name, "ATMTP_DEBUG_LEVEL") != 0 && + strcmp(name, "ATMTP_ENABLED") != 0) { + // + // [dann 2007-04-04] ATMTP ^^ + if ( confirm_init() ) { + DEBUG_OUT("error: %s is already initialized.\n", m_name); + DEBUG_OUT(" : setting parameters after initialization is unsupported\n"); + return (Sim_Set_Illegal_Value); + } + // [dann 2007-04-04] ATMTP VV + // + } + // + // [dann 2007-04-04] ATMTP ^^ + + set_error_t result = initvar_set_attr( (void *) name, NULL, value ); + (*m_generate_values_f)(); + return (result); +} + +/** print out a list of valid parameters */ +//************************************************************************** +void initvar_t::list_param( FILE *fp ) +{ + if (!fp) + fp = stdout; + +#define PARAM( NAME ) \ + fprintf( fp, "%-44.44s: %26d\n", #NAME, NAME ); +#define PARAM_UINT( NAME ) \ + fprintf( fp, "%-44.44s: %26u\n", #NAME, NAME ); +#define PARAM_ULONG( NAME ) \ + fprintf( fp, "%-44.44s: %26llu\n", #NAME, NAME ); +#define PARAM_BOOL( NAME ) \ + if (NAME == true) { \ + fprintf( fp, "%-44.44s: %26.26s\n", #NAME, "true" ); \ + } else { \ + fprintf( fp, "%-44.44s: %26.26s\n", #NAME, "false" );\ + } +#define PARAM_DOUBLE( NAME ) \ + fprintf( fp, "%-44.44s: %26f\n", #NAME, NAME ); +#define PARAM_STRING( NAME ) \ + if ( NAME != NULL ) { \ + fprintf( fp, "%-44.44s: %26.26s\n", #NAME, NAME ); \ + } +#define PARAM_ARRAY( PTYPE, NAME, ARRAY_SIZE ) \ + fprintf( fp, "%-44.44s: (", #NAME ); \ + for (int i = 0; i < ARRAY_SIZE; i++) { \ + if ( i != 0 ) { \ + fprintf( fp, ", " ); \ + } \ + fprintf( fp, "%d", NAME[i] ); \ + } \ + fprintf( fp, ")\n" ); + +#include "mem/ruby/config/config.hh" +#undef PARAM +#undef PARAM_UINT +#undef PARAM_ULONG +#undef PARAM_BOOL +#undef PARAM_DOUBLE +#undef PARAM_STRING +#undef PARAM_ARRAY +} + +//************************************************************************** +const char *initvar_t::get_config_name( void ) +{ + if (m_config_filename == NULL) { + return "default"; + } + return m_config_filename; +} + |