diff options
-rw-r--r-- | src/base/cprintf.cc | 17 | ||||
-rw-r--r-- | src/base/cprintf.hh | 35 | ||||
-rw-r--r-- | src/base/cprintf_formats.hh | 4 | ||||
-rw-r--r-- | src/unittest/cprintftest.cc | 9 | ||||
-rw-r--r-- | util/m5/m5.c | 317 | ||||
-rw-r--r-- | util/mkblankimage.sh | 219 |
6 files changed, 471 insertions, 130 deletions
diff --git a/src/base/cprintf.cc b/src/base/cprintf.cc index d4ba9ca21..5c11e501c 100644 --- a/src/base/cprintf.cc +++ b/src/base/cprintf.cc @@ -40,7 +40,7 @@ using namespace std; namespace cp { Print::Print(std::ostream &stream, const std::string &format) - : stream(stream), format(format.c_str()), ptr(format.c_str()) + : stream(stream), format(format.c_str()), ptr(format.c_str()), cont(false) { saved_flags = stream.flags(); saved_fill = stream.fill(); @@ -48,7 +48,7 @@ Print::Print(std::ostream &stream, const std::string &format) } Print::Print(std::ostream &stream, const char *format) - : stream(stream), format(format), ptr(format) + : stream(stream), format(format), ptr(format), cont(false) { saved_flags = stream.flags(); saved_fill = stream.fill(); @@ -60,8 +60,10 @@ Print::~Print() } void -Print::process(Format &fmt) +Print::process() { + fmt.clear(); + size_t len; while (*ptr) { @@ -221,8 +223,15 @@ Print::process(Format &fmt) number = number * 10 + (*ptr - '0'); break; + case '*': + if (have_precision) + fmt.get_precision = true; + else + fmt.get_width = true; + break; + case '%': - assert("we shouldn't get here"); + assert(false && "we shouldn't get here"); break; default: diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh index cff73a228..2920e210d 100644 --- a/src/base/cprintf.hh +++ b/src/base/cprintf.hh @@ -51,24 +51,53 @@ struct Print std::ostream &stream; const char *format; const char *ptr; + bool cont; std::ios::fmtflags saved_flags; char saved_fill; int saved_precision; - void process(Format &fmt); + Format fmt; + void process(); public: Print(std::ostream &stream, const std::string &format); Print(std::ostream &stream, const char *format); ~Print(); + int + get_number(int data) + { + return data; + } + + template <typename T> + int + get_number(const T& data) + { + return 0; + } + template <typename T> void add_arg(const T &data) { - Format fmt; - process(fmt); + if (!cont) + process(); + + if (fmt.get_width) { + fmt.get_width = false; + cont = true; + fmt.width = get_number(data); + return; + } + + if (fmt.get_precision) { + fmt.get_precision = false; + cont = true; + fmt.precision = get_number(data); + return; + } switch (fmt.format) { case Format::character: diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh index 75157a540..6bf6b2b66 100644 --- a/src/base/cprintf_formats.hh +++ b/src/base/cprintf_formats.hh @@ -50,6 +50,8 @@ struct Format enum { best, fixed, scientific } float_format; int precision; int width; + bool get_precision; + bool get_width; Format() { clear(); } @@ -65,6 +67,8 @@ struct Format format = none; precision = -1; width = 0; + get_precision = false; + get_width = false; } }; diff --git a/src/unittest/cprintftest.cc b/src/unittest/cprintftest.cc index 1438f194b..6722ce6a3 100644 --- a/src/unittest/cprintftest.cc +++ b/src/unittest/cprintftest.cc @@ -167,6 +167,13 @@ main() cprintf("%c %c\n", 'c', 65); - cout << '9'; + cout << '9' << endl; + + cout << endl; + + cprintf("%08.4f\n", 99.99); + cprintf("%0*.*f\n", 8, 4, 99.99); + cprintf("%07.*f\n", 4, 1.234); + cprintf("%#0*x\n", 9, 123412); return 0; } diff --git a/util/m5/m5.c b/util/m5/m5.c index b103796a8..7747fc0bc 100644 --- a/util/m5/m5.c +++ b/util/m5/m5.c @@ -28,7 +28,14 @@ * Authors: Nathan Binkert */ +#ifdef linux +#define _GNU_SOURCE +#include <sched.h> +#endif + #include <inttypes.h> +#include <err.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -37,154 +44,220 @@ #include "m5op.h" char *progname; +char *command = "unspecified"; +void usage(); void -usage() +parse_int_args(int argc, char *argv[], uint64_t ints[], int len) { - printf("usage: m5 initparam\n" - " m5 sw99param\n" - " m5 exit [delay]\n" - " m5 resetstats [delay [period]]\n" - " m5 dumpstats [delay [period]]\n" - " m5 dumpresetstats [delay [period]]\n" - " m5 checkpoint [delay [period]]\n" - " m5 readfile\n" - "\n" - "All times in nanoseconds!\n"); - exit(1); -} + if (argc > len) + usage(); -#define COMPARE(X) (strcmp(X, command) == 0) + int i; + for (i = 0; i < len; ++i) + ints[i] = (i < argc) ? strtoul(argv[i], NULL, 0) : 0; +} int -main(int argc, char *argv[]) +read_file(int dest_fid) { - char *command; - uint64_t param; - uint64_t arg1 = 0; - uint64_t arg2 = 0; + char buf[256*1024]; + int offset = 0; + int len; - progname = argv[0]; - if (argc < 2) + while ((len = m5_readfile(buf, sizeof(buf), offset)) > 0) { + write(dest_fid, buf, len); + offset += len; + } +} + +void +do_exit(int argc, char *argv[]) +{ + if (argc > 1) usage(); - command = argv[1]; + m5_exit((argc > 0) ? strtoul(argv[0], NULL, 0) : 0); +} - if (COMPARE("initparam")) { - if (argc != 2) - usage(); +void +do_reset_stats(int argc, char *argv[]) +{ + uint64_t ints[2]; + parse_int_args(argc, argv, ints, 2); + m5_reset_stats(ints[0], ints[1]); +} - printf("%ld", m5_initparam()); - return 0; - } +void +do_dump_stats(int argc, char *argv[]) +{ + uint64_t ints[2]; + parse_int_args(argc, argv, ints, 2); + m5_dump_stats(ints[0], ints[1]); +} - if (COMPARE("sw99param")) { - if (argc != 2) - usage(); +void +do_dump_reset_stats(int argc, char *argv[]) +{ + uint64_t ints[2]; + parse_int_args(argc, argv, ints, 2); + m5_dumpreset_stats(ints[0], ints[1]); +} - param = m5_initparam(); - // run-time, rampup-time, rampdown-time, warmup-time, connections - printf("%d %d %d %d %d", (param >> 48) & 0xfff, - (param >> 36) & 0xfff, (param >> 24) & 0xfff, - (param >> 12) & 0xfff, (param >> 0) & 0xfff); +void +do_read_file(int argc, char *argv[]) +{ + if (argc > 0) + usage(); - return 0; - } + read_file(STDOUT_FILENO); +} - if (COMPARE("exit")) { - switch (argc) { - case 3: - arg1 = strtoul(argv[2], NULL, 0); - case 2: - m5_exit(arg1); - return 0; - - default: - usage(); - } - } +void +do_exec_file(int argc, char *argv[]) +{ + if (argc > 0) + usage(); - if (COMPARE("resetstats")) { - switch (argc) { - case 4: - arg2 = strtoul(argv[3], NULL, 0); - case 3: - arg1 = strtoul(argv[2], NULL, 0); - case 2: - m5_reset_stats(arg1, arg2); - return 0; - - default: - usage(); - } - } + const char *destname = "/tmp/execfile"; - if (COMPARE("dumpstats")) { - switch (argc) { - case 4: - arg2 = strtoul(argv[3], NULL, 0); - case 3: - arg1 = strtoul(argv[2], NULL, 0); - case 2: - m5_dump_stats(arg1, arg2); - return 0; - - default: - usage(); - } + int fid = open(destname, O_WRONLY, 0777); + int len = read_file(fid); + close(fid); + if (len > 0) { + execl(destname, "execfile", NULL); + err(1, "execl failed!"); } +} - if (COMPARE("dumpresetstats")) { - switch (argc) { - case 4: - arg2 = strtoul(argv[3], NULL, 0); - case 3: - arg1 = strtoul(argv[2], NULL, 0); - case 2: - m5_dumpreset_stats(arg1, arg2); - return 0; - - default: - usage(); - } - } +void +do_checkpoint(int argc, char *argv[]) +{ + uint64_t ints[2]; + parse_int_args(argc, argv, ints, 2); + m5_checkpoint(ints[0], ints[1]); +} + +void +do_load_symbol(int argc, char *argv[]) +{ + if (argc != 2) + usage(); - if (COMPARE("readfile")) { - char buf[256*1024]; - int offset = 0; - int len; + uint64_t addr = strtoul(argv[0], NULL, 0); + char *symbol = argv[1]; + m5_loadsymbol(addr, symbol); +} - if (argc != 2) - usage(); +void +do_initparam(int argc, char *argv[]) +{ + if (argc != 0) + usage(); - while ((len = m5_readfile(buf, sizeof(buf), offset)) > 0) { - write(STDOUT_FILENO, buf, len); - offset += len; - } + + printf("%ld", m5_initparam()); +} - return 0; - } +void +do_sw99param(int argc, char *argv[]) +{ + if (argc != 0) + usage(); + + uint64_t param = m5_initparam(); + + // run-time, rampup-time, rampdown-time, warmup-time, connections + printf("%d %d %d %d %d", (param >> 48) & 0xfff, + (param >> 36) & 0xfff, (param >> 24) & 0xfff, + (param >> 12) & 0xfff, (param >> 0) & 0xfff); +} + +#ifdef linux +void +do_pin(int argc, char *argv[]) +{ + if (argc < 2) + usage(); + + cpu_set_t mask; + CPU_ZERO(&mask); + + const char *sep = ","; + char *target = strtok(argv[0], sep); + while (target) { + CPU_SET(atoi(target), &mask); + target = strtok(NULL, sep); + } + + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) < 0) + err(1, "setaffinity"); + + execvp(argv[1], &argv[1]); + err(1, "execvp failed!"); +} +#endif + +struct MainFunc +{ + char *name; + void (*func)(int argc, char *argv[]); + char *usage; +}; - if (COMPARE("checkpoint")) { - switch (argc) { - case 4: - arg2 = strtoul(argv[3], NULL, 0); - case 3: - arg1 = strtoul(argv[2], NULL, 0); - case 2: - m5_checkpoint(arg1, arg2); - return 0; - - default: - usage(); - } - - return 0; +struct MainFunc mainfuncs[] = { + { "exit", do_exit, "[delay]" }, + { "resetstats", do_reset_stats, "[delay [period]]" }, + { "dumpstats", do_dump_stats, "[delay [period]]" }, + { "dumpresetstats", do_dump_reset_stats, "[delay [period]]" }, + { "readfile", do_read_file, "[filename]" }, + { "execfile", do_exec_file, "<filename>" }, + { "checkpoint", do_checkpoint, "[delay [period]]" }, + { "loadsymbol", do_load_symbol, "<address> <symbol>" }, + { "initparam", do_initparam, "" }, + { "sw99param", do_sw99param, "" }, +#ifdef linux + { "pin", do_pin, "<cpu> <program> [args ...]" } +#endif +}; +int numfuncs = sizeof(mainfuncs) / sizeof(mainfuncs[0]); + +void +usage() +{ + int i; + + for (i = 0; i < numfuncs; ++i) { + char *header = i ? "" : "usage:"; + fprintf(stderr, "%-6s %s %s %s\n", + header, progname, mainfuncs[i].name, mainfuncs[i].usage); } + fprintf(stderr, "\n"); + fprintf(stderr, "All times in nanoseconds!\n"); + + exit(1); +} - if (COMPARE("loadsymbol")) { - m5_loadsymbol(arg1); - return 0; +int +main(int argc, char *argv[]) +{ + progname = argv[0]; + if (argc < 2) + usage(1); + + command = argv[1]; + + argv += 2; + argc -= 2; + + int i; + for (i = 0; i < numfuncs; ++i) { + if (strcmp(command, mainfuncs[i].name) != 0) + continue; + + mainfuncs[i].func(argc, argv); + exit(0); } - usage(); + + usage(1); } diff --git a/util/mkblankimage.sh b/util/mkblankimage.sh new file mode 100644 index 000000000..43a3cca29 --- /dev/null +++ b/util/mkblankimage.sh @@ -0,0 +1,219 @@ +#!/bin/sh +# +# makeblankimage.sh +# Make a blank M5 disk image +# + +while getopts "m" OPT +do + case "$OPT" in + m) MOUNT_IT=1 + esac +done + +DEBUG=0 + +if [ $DEBUG -ne 0 ]; then + set -x -e + OUTPUT="" +else + OUTPUT="> /dev/null 2>&1" +fi + +abort() { + echo $@ + exec /bin/false +} + +find_prog() { + PROG_PATH=`which $1` + if [ $? -ne 0 ]; then + abort "Unable to find program $1, check your PATH variable" + fi + echo $PROG_PATH +} + +run_priv() { + if [ "$HAVE_SUDO" = "y" ]; then + eval $SUDO $@ $OUTPUT + else + eval $@ $OUTPUT + fi + + if [ $? -ne 0 ]; then + abort "Failed to run $@ as root" + fi +} + +usage() { + abort "Usage: $0 [root-path to copy] [extra ownership commands ...]" +} + +# Setup PATH to look in the sbins +export PATH=$PATH:/sbin:/usr/sbin + +# Get all of the programs needed, or exit +DD=`find_prog dd` +SFDISK=`find_prog sfdisk` +LOSETUP=`find_prog losetup` +SUDO=`find_prog sudo` +MKE2FS=`find_prog mke2fs` +MKDIR=`find_prog mkdir` +MOUNT=`find_prog mount` +UMOUNT=`find_prog umount` +WHOAMI=`find_prog whoami` +CP=`find_prog cp` +CHOWN=`find_prog chown` + +# Prompt for the root password, if needed +CUR_USER=`$WHOAMI` + +if [ $# -ge 1 ]; then + if [ ! $MOUNT_IT ]; then + ROOT_PATH=$1 + + if [ ! -d $ROOT_PATH ]; then + usage + fi + else + ROOT_PATH="" + fi +else + ROOT_PATH="" +fi + +if [ ! "$CUR_USER" = "root" ]; then + echo -n "Do you have sudo access? [y/n] " + read HAVE_SUDO + + if [ ! "$HAVE_SUDO" = "y" ]; then + abort "You must have sudo access or run this script as root" + fi +fi + +echo -n "How large do you want this disk image (in MB): " +read USER_SIZE_MB + +# size in bytes = SIZE_MB * 1024 * 1024 +# size in blocks = SIZE_BYTE / 512 +let BLK_SIZE=$USER_SIZE_MB*1024*2 + +let MAX_LBA=16383*16*63 + +if [ $BLK_SIZE -ge $MAX_LBA ]; then + CYLS=16383 + HEADS=16 + SECTORS=63 +else + # Set Sectors + if [ $BLK_SIZE -ge 63 ]; then + SECTORS=63 + else + SECTORS=$BLK_SIZE + fi + + # Set Heads + let HEAD_SIZE=$BLK_SIZE/$SECTORS + + if [ $HEAD_SIZE -ge 16 ]; then + HEADS=16 + else + HEADS=$BLK_SIZE + fi + + # Set Cylinders + let SEC_HEAD=$SECTORS*$HEADS + let CYLS=$BLK_SIZE/$SEC_HEAD +fi + +# Recalculate number of sectors +let BLK_SIZE=$CYLS*$HEADS*$SECTORS + +# Get the name of the file and directory to build in +echo -n "What directory would you like to build the image in? " +read IMAGE_DIR + +if [ ! -d $IMAGE_DIR ]; then + abort "The directory $IMAGE_DIR does not exist" +fi + +echo -n "What would you like to name the image? " +read IMAGE_NAME + +IMAGE_FILE=$IMAGE_DIR/$IMAGE_NAME + +# DD the blank image +echo +echo "dd'ing the blank image (this make take a while)..." +eval $DD if=/dev/zero of=$IMAGE_FILE bs=512 count=$BLK_SIZE $OUTPUT +if [ $? -ne 0 ]; then + abort "Unable to create the blank image $IMAGE_NAME in $IMAGE_DIR" +fi + +# losetup the image with no offset to do the fdisk +echo +echo "Binding the image and partitioning..." +run_priv $LOSETUP /dev/loop0 $IMAGE_FILE +if [ $? -ne 0 ]; then + abort "losetup to /dev/loop0 failed, make sure nothing is setup on loop0 (check by typing 'mount') " +fi + +# fdisk the image +run_priv $SFDISK --no-reread -D -C $CYLS -H $HEADS -S $SECTORS /dev/loop0 <<EOF +0, +; +; +; +EOF + +# Un-losetup the image +run_priv $LOSETUP -d /dev/loop0 + +# Mount the image with an offset and make the filesystem +echo +echo "Remounting image and formatting..." +let BASE_OFFSET=63*512 + +run_priv $LOSETUP -o $BASE_OFFSET /dev/loop0 $IMAGE_FILE + +run_priv $MKE2FS /dev/loop0 + +# If a root path was specified then copy the root path into the image +if [ ! -z "$ROOT_PATH" ]; then + echo "Copying root from $ROOT_PATH to image file" + + run_priv $MKDIR -p /tmp/mnt + + run_priv $MOUNT /dev/loop0 /tmp/mnt + + run_priv $CP -a $ROOT_PATH/* /tmp/mnt + + run_priv $CHOWN -R root.root /tmp/mnt + + # run extra permissions while disk is mounted + TOPDIR=`pwd` + cd /tmp/mnt + i=2 + while [ $i -le $# ]; do + run_priv ${!i} + let i=i+1 + done + cd $TOPDIR + + run_priv $UMOUNT /tmp/mnt +fi + +run_priv $LOSETUP -d /dev/loop0 + + +if [ $MOUNT_IT -eq 1 ]; then + run_priv mount -o loop,offset=$BASE_OFFSET $IMAGE_FILE /tmp/mnt +else + echo + echo "Disk image creation complete." + echo "To mount the image, run the following commands:" + echo "# $MOUNT -o loop,offset=$BASE_OFFSET $IMAGE_FILE /mount/point" + echo + echo "And to unmount the image, run:" + echo "# $UMOUNT /mount/point" +fi; |