From d751cecbb1ca1b7ac0a7bc8492e0e61e6c5fc0c7 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 17 May 2011 20:39:40 +0000 Subject: * tools/build/.cvsignore, tools/build/ChangeLog, tools/build/Makefile.am, tools/build/README, tools/build/binpatch.c, tools/build/cklength.c, tools/build/config.h.in, tools/build/configure.ac, tools/build/cvsignore-add.sh, tools/build/doxy-filter, tools/build/eolstrip.c, tools/build/install-if-change.in, tools/build/multigen, tools/build/packhex.c, tools/build/rtems-bin2c.c, tools/build/search-id.sh, tools/build/unhex.c, tools/cpu/.cvsignore, tools/cpu/ChangeLog, tools/cpu/Makefile.am, tools/cpu/configure.ac, tools/cpu/generic/.cvsignore, tools/cpu/generic/ChangeLog, tools/cpu/generic/Makefile.am, tools/cpu/generic/configure.ac, tools/cpu/generic/size_rtems.in, tools/cpu/nios2/.cvsignore, tools/cpu/nios2/ChangeLog, tools/cpu/nios2/Makefile.am, tools/cpu/nios2/README, tools/cpu/nios2/bridges.c, tools/cpu/nios2/bridges.h, tools/cpu/nios2/clocks.c, tools/cpu/nios2/clocks.h, tools/cpu/nios2/configure.ac, tools/cpu/nios2/devices.c, tools/cpu/nios2/devices.h, tools/cpu/nios2/linkcmds.c, tools/cpu/nios2/linkcmds.h, tools/cpu/nios2/memory.c, tools/cpu/nios2/memory.h, tools/cpu/nios2/nios2gen.c, tools/cpu/nios2/output.c, tools/cpu/nios2/output.h, tools/cpu/nios2/ptf.c, tools/cpu/nios2/ptf.h, tools/cpu/nios2/sample.ptf, tools/cpu/sh/.cvsignore, tools/cpu/sh/AUTHORS, tools/cpu/sh/COPYING, tools/cpu/sh/ChangeLog, tools/cpu/sh/Makefile.am, tools/cpu/sh/TODO, tools/cpu/sh/configure.ac, tools/cpu/sh/sci.c, tools/cpu/sh/sci.h, tools/cpu/sh/shgen.c: New files. --- tools/build/.cvsignore | 18 + tools/build/ChangeLog | 209 ++++++++++ tools/build/Makefile.am | 26 ++ tools/build/README | 10 + tools/build/binpatch.c | 156 +++++++ tools/build/cklength.c | 377 +++++++++++++++++ tools/build/config.h.in | 55 +++ tools/build/configure.ac | 26 ++ tools/build/cvsignore-add.sh | 25 ++ tools/build/doxy-filter | 21 + tools/build/eolstrip.c | 366 +++++++++++++++++ tools/build/install-if-change.in | 142 +++++++ tools/build/multigen | 173 ++++++++ tools/build/packhex.c | 565 ++++++++++++++++++++++++++ tools/build/rtems-bin2c.c | 291 +++++++++++++ tools/build/search-id.sh | 15 + tools/build/unhex.c | 737 +++++++++++++++++++++++++++++++++ tools/cpu/.cvsignore | 14 + tools/cpu/ChangeLog | 123 ++++++ tools/cpu/Makefile.am | 12 + tools/cpu/configure.ac | 28 ++ tools/cpu/generic/.cvsignore | 15 + tools/cpu/generic/ChangeLog | 78 ++++ tools/cpu/generic/Makefile.am | 9 + tools/cpu/generic/configure.ac | 23 ++ tools/cpu/generic/size_rtems.in | 284 +++++++++++++ tools/cpu/nios2/.cvsignore | 14 + tools/cpu/nios2/ChangeLog | 34 ++ tools/cpu/nios2/Makefile.am | 25 ++ tools/cpu/nios2/README | 148 +++++++ tools/cpu/nios2/bridges.c | 114 ++++++ tools/cpu/nios2/bridges.h | 31 ++ tools/cpu/nios2/clocks.c | 77 ++++ tools/cpu/nios2/clocks.h | 28 ++ tools/cpu/nios2/configure.ac | 23 ++ tools/cpu/nios2/devices.c | 132 ++++++ tools/cpu/nios2/devices.h | 32 ++ tools/cpu/nios2/linkcmds.c | 122 ++++++ tools/cpu/nios2/linkcmds.h | 25 ++ tools/cpu/nios2/memory.c | 104 +++++ tools/cpu/nios2/memory.h | 29 ++ tools/cpu/nios2/nios2gen.c | 496 +++++++++++++++++++++++ tools/cpu/nios2/output.c | 195 +++++++++ tools/cpu/nios2/output.h | 27 ++ tools/cpu/nios2/ptf.c | 853 +++++++++++++++++++++++++++++++++++++++ tools/cpu/nios2/ptf.h | 71 ++++ tools/cpu/nios2/sample.ptf | 462 +++++++++++++++++++++ tools/cpu/sh/.cvsignore | 14 + tools/cpu/sh/AUTHORS | 3 + tools/cpu/sh/COPYING | 343 ++++++++++++++++ tools/cpu/sh/ChangeLog | 86 ++++ tools/cpu/sh/Makefile.am | 18 + tools/cpu/sh/TODO | 13 + tools/cpu/sh/configure.ac | 25 ++ tools/cpu/sh/sci.c | 165 ++++++++ tools/cpu/sh/sci.h | 11 + tools/cpu/sh/shgen.c | 114 ++++++ 57 files changed, 7632 insertions(+) create mode 100644 tools/build/.cvsignore create mode 100644 tools/build/ChangeLog create mode 100644 tools/build/Makefile.am create mode 100644 tools/build/README create mode 100644 tools/build/binpatch.c create mode 100644 tools/build/cklength.c create mode 100644 tools/build/config.h.in create mode 100644 tools/build/configure.ac create mode 100755 tools/build/cvsignore-add.sh create mode 100755 tools/build/doxy-filter create mode 100644 tools/build/eolstrip.c create mode 100644 tools/build/install-if-change.in create mode 100755 tools/build/multigen create mode 100644 tools/build/packhex.c create mode 100644 tools/build/rtems-bin2c.c create mode 100755 tools/build/search-id.sh create mode 100644 tools/build/unhex.c create mode 100644 tools/cpu/.cvsignore create mode 100644 tools/cpu/ChangeLog create mode 100644 tools/cpu/Makefile.am create mode 100644 tools/cpu/configure.ac create mode 100644 tools/cpu/generic/.cvsignore create mode 100644 tools/cpu/generic/ChangeLog create mode 100644 tools/cpu/generic/Makefile.am create mode 100644 tools/cpu/generic/configure.ac create mode 100644 tools/cpu/generic/size_rtems.in create mode 100644 tools/cpu/nios2/.cvsignore create mode 100644 tools/cpu/nios2/ChangeLog create mode 100644 tools/cpu/nios2/Makefile.am create mode 100644 tools/cpu/nios2/README create mode 100644 tools/cpu/nios2/bridges.c create mode 100644 tools/cpu/nios2/bridges.h create mode 100644 tools/cpu/nios2/clocks.c create mode 100644 tools/cpu/nios2/clocks.h create mode 100644 tools/cpu/nios2/configure.ac create mode 100644 tools/cpu/nios2/devices.c create mode 100644 tools/cpu/nios2/devices.h create mode 100644 tools/cpu/nios2/linkcmds.c create mode 100644 tools/cpu/nios2/linkcmds.h create mode 100644 tools/cpu/nios2/memory.c create mode 100644 tools/cpu/nios2/memory.h create mode 100644 tools/cpu/nios2/nios2gen.c create mode 100644 tools/cpu/nios2/output.c create mode 100644 tools/cpu/nios2/output.h create mode 100644 tools/cpu/nios2/ptf.c create mode 100644 tools/cpu/nios2/ptf.h create mode 100644 tools/cpu/nios2/sample.ptf create mode 100644 tools/cpu/sh/.cvsignore create mode 100644 tools/cpu/sh/AUTHORS create mode 100644 tools/cpu/sh/COPYING create mode 100644 tools/cpu/sh/ChangeLog create mode 100644 tools/cpu/sh/Makefile.am create mode 100644 tools/cpu/sh/TODO create mode 100644 tools/cpu/sh/configure.ac create mode 100644 tools/cpu/sh/sci.c create mode 100644 tools/cpu/sh/sci.h create mode 100644 tools/cpu/sh/shgen.c (limited to 'tools') diff --git a/tools/build/.cvsignore b/tools/build/.cvsignore new file mode 100644 index 0000000000..d0e6e41377 --- /dev/null +++ b/tools/build/.cvsignore @@ -0,0 +1,18 @@ +aclocal.m4 +autom4te*.cache +config.cache +config.guess +config.h +config.h.in +config.log +config.status +config.sub +configure +depcomp +install-if-change +install-sh +Makefile +Makefile.in +missing +mkinstalldirs +stamp-h.in diff --git a/tools/build/ChangeLog b/tools/build/ChangeLog new file mode 100644 index 0000000000..e3e344cbcb --- /dev/null +++ b/tools/build/ChangeLog @@ -0,0 +1,209 @@ +2011-02-02 Ralf Corsépius + + * configure.ac: Require autoconf-2.68, automake-1.11.1. + +2010-07-30 Ralf Corsépius + + * rtems-bin2c.c: Fix memory leak in '.c' suffix strip. + Also strip '.h' suffix. + +2010-07-30 Ralf Corsépius + + * rtems-bin2c.c: Make -v (verbose) working. + +2010-07-30 Ralf Corsépius + + * configure.ac: Check for libgen.h, basename. + * rtems-bin2c.c: Use basename(3) instead of strrchr cascade. + Introduce ifbasename. Use ifbasename in generated files. + +2010-07-29 Ralf Corsépius + + * rtems-bin2c.c: Add -C and -H options. + +2010-03-12 Joel Sherrill + + * eolstrip.c: Readdress use of ctype methods per recommendation from + D.J. Delorie on the newlib mailing list. We should pass an unsigned + char into these methods. + +2007-09-18 Joel Sherrill + + * Makefile.am: Rename bin2c to rtems-bin2c. + +2007-09-10 Joel Sherrill + + * bin2c.c: Updated license after author changed it. + +2007-09-07 Joel Sherrill + + * bin2c.c: Update comments. + +2007-09-04 Joel Sherrill + + * bin2c.c: Significant improvements -- add multiple options, generate + both C and H files, do not always generate static. fix indentation, + add comments. + +2007-09-04 Joel Sherrill + + * bin2c.c: New file. + http://www.wxwidgets.org/wiki/index.php/Embedding_PNG_Images-Bin2c_In_C + +2007-09-04 Joel Sherrill + + * Makefile.am: Add bin2c so we can have a more reliable way to convert + binary files to objects. If they are in C, we can use the correct CPU + CFLAGS and they will link easier. + +2006-12-02 Ralf Corsépius + + * configure.ac: New BUG-REPORT address. + +2006-10-17 Ralf Corsépius + + * configure.ac: Require autoconf-2.60. Require automake-1.10. + +2006-07-13 Ralf Corsepius + + * doxy-filter: New. + * Makefile.am: Add doxy-filter. + +2006-07-11 Ralf Corsepius + + * ampolish3.in: Remove. + * Makefile.am: Remove ampolish3. + * configure.ac: Remove ampolish3, perl. + +2006-01-14 Ralf Corsepius + + * ampolish3.in: Check Makefile.am for SUBDIRS. + Add all-am: for PREINSTALL_FILES. + +2006-01-12 Ralf Corsepius + + * ampolish3.in: Add all: for PREINSTALL_FILES. + Add all-local for TMPINSTALL_FILES. + Misc bug fixes. + +2006-01-12 Ralf Corsepius + + * ampolish3.in: Check if Makefile.am already contains CLEANFILES or + DISTCLEANFILES. + +2006-01-10 Ralf Corsepius + + * ampolish3.in: Update. + +2005-10-25 Ralf Corsepius + + * ampolish3.in: Sync with private bleeding-edge . + +2005-10-24 Ralf Corsepius + + * ampolish3.in: Use @PERL@, partial update from local sources. + +2005-10-24 Ralf Corsepius + + * configure.ac: Add ampolish3. + * Makefile.am: Add ampolish3. + * ampolish3.in: New. + +2004-09-24 Ralf Corsepius + + * configure.ac: Require automake > 1.9. + +2004-02-20 Ralf Corsepius + + * Makefile.am: Add EXTRA_DIST = search-id.sh multigen + cvsignore-add.sh. + +2003-12-12 Ralf Corsepius + + * configure.ac: Require automake >= 1.8, autoconf >= 2.59. + +2003-08-11 Ralf Corsepius + + * configure.ac: Use rtems-bugs@rtems.com as bug report email address. + +2003-03-07 Ralf Corsepius + + * configure.ac: Add AC_CHECK_HEADERS(getopt.h) to work around a bug + in autoconf-2.57. + +2003-03-06 Ralf Corsepius + + * configure.ac: Remove AC_CONFIG_AUX_DIR. + +2003-03-02 Ralf Corsepius + + * configure.ac: Add AC_CHECK_HEADERS. + +2003-02-11 Ralf Corsepius + + * configure.ac: AM_INIT_AUTOMAKE([1.7.2]). + +2003-02-11 Ralf Corsepius + + * configure.ac: AC_PREREQ(2.57). + +2002-10-21 Ralf Corsepius + + * .cvsignore: Reformat. + Add autom4te*cache. + Remove autom4te.cache. + +2002-10-02 Chris Johns + + * cvsignore-add.sh: Script to append a specific file to all + .cvsignore files if the files exists is a specific directory. + +2002-05-01 Joel Sherrill + + * lock-directory.in, unlock-directory.in: Removed. + * Makefile.am, README, .cvsignore: Updated to reflect above. + +2002-04-01 Ralf Corsepius + + * configure.ac: Remove AC_EXEEXT (obsolete). + +2002-03-27 Ralf Corsepius + + * configure.ac: + AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS). + AM_INIT_AUTOMAKE([no-define foreign 1.6]). + * Makefile.am: Remove AUTOMAKE_OPTIONS. + +2001-10-11 Ralf Corsepius + + * .cvsignore: Add autom4te.cache for autoconf > 2.52. + * configure.in: Remove. + * configure.ac: New file, generated from configure.in by autoupdate. + +2001-01-24 Ralf Corsepius + + * config.h.in: Automatically generated. Remove from CVS. + +2000-11-09 Ralf Corsepius + + * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS. + +2000-11-02 Ralf Corsepius + + * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal. + +2000-10-30 Ralf Corsepius + + * Makefile.am: Switch to GNU-canonicalized autoconf macros. + +2000-08-10 Ralf Corsepius + + * multigen: Fix BARE_CPU_CFLAGS. + +2000-08-06 Ralf Corsepius + + * multigen: Fix usage. + +2000-08-10 Joel Sherrill + + * ChangeLog: New file. diff --git a/tools/build/Makefile.am b/tools/build/Makefile.am new file mode 100644 index 0000000000..f58624929f --- /dev/null +++ b/tools/build/Makefile.am @@ -0,0 +1,26 @@ +## +## $Id$ +## + +ACLOCAL_AMFLAGS = -I ../../aclocal + +bin_PROGRAMS = cklength eolstrip packhex unhex rtems-bin2c + +noinst_PROGRAMS = binpatch + +cklength_SOURCES = cklength.c +eolstrip_SOURCES = eolstrip.c +packhex_SOURCES = packhex.c +unhex_SOURCES = unhex.c +binpatch_SOURCES = binpatch.c +rtems_bin2c_SOURCES = rtems-bin2c.c + +bin_SCRIPTS = install-if-change + +noinst_SCRIPTS = search-id.sh multigen cvsignore-add.sh +EXTRA_DIST = search-id.sh multigen cvsignore-add.sh + +noinst_SCRIPTS += doxy-filter +EXTRA_DIST += doxy-filter + +include $(top_srcdir)/../../automake/host.am diff --git a/tools/build/README b/tools/build/README new file mode 100644 index 0000000000..18899c3c06 --- /dev/null +++ b/tools/build/README @@ -0,0 +1,10 @@ +# +# $Id$ +# + +Misc. support tools for RTEMS workspaces. + +install-if-change + Smart install script that also can append suffixes as it + installs (suffixes used for debug and profile variants). + Requires bash or ksh. diff --git a/tools/build/binpatch.c b/tools/build/binpatch.c new file mode 100644 index 0000000000..b9e2ac1a06 --- /dev/null +++ b/tools/build/binpatch.c @@ -0,0 +1,156 @@ +/* + * $Id$ + */ + + +#include +#include + +/* + * This function will patch binary file + */ + + +static char buf[512]; + +static void +usage(void) +{ + printf("usage: binpatch [-h] " + "[ [ []]]\n"); + printf("this function patches binary file at specified offset with\n"); + printf("up to 4 bytes provided on command line \n"); + printf("-h - prints this message\n\n"); + printf(" - output file\n"); + printf(" - input ifile\n"); + printf(" - relocation address of image\n"); + printf(" - offset of patch, offset in file is at off - reloc\n"); + printf(" - byte 0 of patch\n"); + printf(" - byte 1 of patch\n"); + printf(" - byte 1 of patch\n"); + printf(" - byte 1 of patch\n"); + + return; +} + +int +main(int argc, char **argv) +{ + int c; + FILE *ofp, *ifp; + char patch[4], *end; + int patchLen, tmp, i, off, cnt, patched, len, reloc; + + + /* parse command line options */ + while ((c = getopt(argc, argv, "h")) >= 0) + { + switch (c) + { + case 'h': + usage(); + return 0; + default: + usage(); + return 1; + } + } + + if(argc < 6) + { + usage(); + return 1; + } + + /* Let us get offset in file */ + reloc = strtol(argv[3], &end, 0); + if(end == argv[3] || off < 0) + { + fprintf(stderr, "bad reloc value %s\n", argv[3]); + return 1; + } + + off = strtol(argv[4], &end, 0); + if(end == argv[4] || off < 0 || off < reloc) + { + fprintf(stderr, "bad offset value %s\n", argv[4]); + return 1; + } + + off -= reloc; + + /* Let us get patch */ + patchLen = argc - 5; + + for(i=0; i 0xff) + { + fprintf(stderr, "bad byte value %s\n", argv[5+i]); + return 1; + } + patch[i] = tmp; + } + + ifp = fopen(argv[2], "r"); + if(ifp == NULL) + { + fprintf(stderr, "unable to open file %s\n", argv[2]); + return 1; + } + + ofp = fopen(argv[1], "w"); + if(ofp == NULL) + { + fprintf(stderr, "unable to open file %s\n", argv[1]); + return 1; + } + + cnt = 0; + patched = 0; + for(;;) + { + len = fread(buf, 1, sizeof(buf), ifp); + + if(len == 0) + { + break; + } + + if(cnt <= off && (cnt + len) > off) + { + /* Perform patch */ + for(i=0; i off && cnt < (off + patchLen)) + { + /* Perform patch */ + for(i=cnt-off; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#ifndef VMS +#ifndef HAVE_STRERROR +extern int sys_nerr; +extern char *sys_errlist[]; + +#define strerror( _err ) \ + ((_err) < sys_nerr) ? sys_errlist [(_err)] : "unknown error" + +#else /* HAVE_STRERROR */ +char *strerror (); +#endif +#else /* VMS */ +char *strerror (int,...); +#endif + + +#define BUFFER_SIZE 512 + +#define SUCCESS 0 +#define FAILURE -1 +#define Failed(x) (((int) (x)) == FAILURE) +#define TRUE 1 +#define FALSE 0 +#define STREQ(a,b) (strcmp(a,b) == 0) +#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + +/* + * Definitions for unsigned "ints"; especially for use in data structures + * that will be shared among (potentially) different cpu's (we punt on + * byte ordering problems tho) + */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +/* + * vars controlled by command line options + */ + +int verbose = FALSE; /* be verbose */ +int report_line_numbers = FALSE; /* report line numbers of offenders */ +int report_line_length = FALSE; /* report line length of offenders */ + +int line_length = 80; /* maximum allowable line length */ + +extern char *optarg; /* getopt(3) control vars */ +extern int optind, opterr; + +char *progname; /* for error() */ + +int process(char *arg); +void error(int errn, ...); +long getparm(char *s, long min, long max, char *msg); + +#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */ +#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */ +#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */ + +#define stol(p) strtol(p, (char **) NULL, 0) +int Open(), Read(), Write(); + +int main( + int argc, + char **argv +) +{ + register int c; + int showusage = FALSE; /* usage error? */ + int rc = 0; + + /* + * figure out invocation leaf-name + */ + + if ((progname = strrchr(argv[0], '/')) == (char *) NULL) + progname = argv[0]; + else + progname++; + + argv[0] = progname; /* for getopt err reporting */ + + /* + * Check options and arguments. + */ + + opterr = 0; /* we'll report all errors */ + while ((c = getopt(argc, argv, GETOPTARGS)) != EOF) + switch (c) + { + case 'l': /* line length */ + line_length = atoi( optarg ); + if ( line_length < 0 || line_length > BUFFER_SIZE ) + error(ERR_FATAL, "(%d) is illegal line length\n",line_length); + break; + + case 'n': /* toggle report_line_numbers */ + report_line_numbers = ! report_line_numbers; + break; + + case 'N': /* toggle both reports */ + report_line_numbers = ! report_line_numbers; + report_line_length = ! report_line_length; + break; + + case 'v': /* toggle verbose */ + verbose = ! verbose; + break; + + case '?': + showusage = TRUE; + } + + if (showusage) + { + (void) fprintf(stderr, "%s", USAGE); + exit(1); + } + + /* + * traverse and process the arguments + */ + + for ( ; argv[optind]; optind++) + if (Failed(process(argv[optind]))) + rc = FAILURE; + + return rc; +} + + +/* + * process(arg) + */ + +int +process(char *arg) +{ + FILE *in; + char *bptr; + char buffer[ BUFFER_SIZE ]; + int line_number; + int length; + int count; + int rc = SUCCESS; /* succeed by default */ + + in = fopen( arg, "r" ); + if (!in) + error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg ); + + count = 0; + + for ( line_number=1 ; ; line_number++ ) { + bptr = fgets( buffer, BUFFER_SIZE, in ); + if (!bptr) + break; + + /* + * Don't count the carriage return. + */ + + length = strlen( buffer ) - 1; + + if ( length <= line_length ) + continue; + + if ( count == 0 ) { + fprintf( stderr, "%s\n", arg ); + if ( !report_line_numbers ) + break; + } + + if ( verbose ) + fprintf( stderr, "TOO LONG:%d: %s\n", line_number, buffer ); + + if ( report_line_numbers ) { + if ( report_line_length ) + fprintf( stderr, "%d: %d\n" , line_number, length ); + else + fprintf( stderr, "%d\n" , line_number ); + } + + count++; + + } + + fclose( in ); + return rc; +} + +/* + * error(errn, arglist) + * report an error to stderr using printf(3) conventions. + * Any output is preceded by ': ' + * + * Uses ERR_FATAL bit to request exit(errn) + * ERR_ABORT to request abort() + * ERR_ERRNO to indicate use of errno instead of argument. + * + * If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its + * associated error message is appended to the output. + */ + +/*VARARGS*/ + +void +error(int error_flag, ...) +{ + va_list arglist; + register char *format; + int local_errno; + + extern int errno; + + (void) fflush(stdout); /* in case stdout/stderr same */ + + local_errno = error_flag & ~ERR_MASK; + if (error_flag & ERR_ERRNO) /* use errno? */ + local_errno = errno; + + va_start(arglist, error_flag); + format = va_arg(arglist, char *); + (void) fprintf(stderr, "%s: ", progname); + (void) vfprintf(stderr, format, arglist); + va_end(arglist); + + if (local_errno) + (void) fprintf(stderr, " (%s)\n", strerror(local_errno)); + + (void) fflush(stderr); + + if (error_flag & (ERR_FATAL | ERR_ABORT)) + { + if (error_flag & ERR_FATAL) + { + error(0, "fatal error, exiting"); + exit(local_errno ? local_errno : 1); + } + else + { + error(0, "fatal error, aborting"); + abort(); + } + } +} + +long +getparm(char *s, + long min, + long max, + char *msg) +{ + long val; + + if ( ! strchr("0123456789-", *s)) + { + error(ERR_FATAL, "'%s' is not a number", s); + return min; + } + + val = strtol(s, (char **) NULL, 0); + if ((val < min) || (val > max)) + { + if (min == max) + error(ERR_FATAL, "%s can only be %ld", s, min); + else + error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max); + } + + return val; +} + + +/* + * Open() + * Perform open(2), returning the file descriptor. Prints + * error message if open fails. + */ + +int +Open(char *file, + int oflag, + int mode) +{ + int O_fd; + + if (Failed(O_fd = open(file, oflag, mode))) + error( + ERR_ERRNO | ERR_FATAL, + "open('%s', 0x%x, 0%o) failed", file, oflag, mode + ); + + return O_fd; +} + +/* + * Read() + * Perform read(2); prints error message if fails. + */ + +int +Read(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = read(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "read(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} + +/* + * Write() + * Perform write(2); prints error message if fails. + */ + +int +Write(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = write(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "write(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} diff --git a/tools/build/config.h.in b/tools/build/config.h.in new file mode 100644 index 0000000000..89117dd249 --- /dev/null +++ b/tools/build/config.h.in @@ -0,0 +1,55 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS diff --git a/tools/build/configure.ac b/tools/build/configure.ac new file mode 100644 index 0000000000..d24f3e2d5a --- /dev/null +++ b/tools/build/configure.ac @@ -0,0 +1,26 @@ +# +# $Id$ +# + +AC_PREREQ([2.68]) +AC_INIT([rtems-tools-build],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([install-if-change.in]) +RTEMS_TOP(../..) + +AC_CANONICAL_HOST + +AM_INIT_AUTOMAKE([no-define foreign 1.11.1]) +AM_MAINTAINER_MODE + +AC_PROG_CC +AC_CHECK_HEADERS([getopt.h libgen.h]) +AC_CHECK_FUNCS(strerror strtol basename) + +RTEMS_PATH_KSH + +AC_CONFIG_HEADERS([config.h]) + +# Explicitly list all Makefiles here +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([install-if-change],[chmod +x install-if-change]) +AC_OUTPUT diff --git a/tools/build/cvsignore-add.sh b/tools/build/cvsignore-add.sh new file mode 100755 index 0000000000..45feab6565 --- /dev/null +++ b/tools/build/cvsignore-add.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Find a file in the directory tree and create or add to a .cvsignore +# file that file name so it is ignored. +# +# Copyright 2001 Cybertec Pty Limited +# All rights reserved. +# +# $Id$ +# + +# +# We need one parameter, the file to add. +# + +if [ $# -eq 0 ]; then + echo "Usage: $0 file, where file is the one to be added." + exit 1 +fi + +for f in `find . -name $1`; +do + echo "`dirname $f`/.cvsignore" + echo "$1" >> `dirname $f`/.cvsignore +done diff --git a/tools/build/doxy-filter b/tools/build/doxy-filter new file mode 100755 index 0000000000..1d47b0806d --- /dev/null +++ b/tools/build/doxy-filter @@ -0,0 +1,21 @@ +#!/bin/sh + +# doxygen input filter +# $Id$ + +# usage: doxy-filter +# Reads and writes to stdout. + +file=$1 + +# Does file contain a doxygen @file directive? +if ! grep -q '@file' $file >/dev/null ; then +# No, add one +echo "/** @file $file */" +cat $file +else +# Yes, adjust path to work around doxygen not being able to +# distinguish file names properly +exec sed -e "s,@file.*$,@file $file," $file +fi + diff --git a/tools/build/eolstrip.c b/tools/build/eolstrip.c new file mode 100644 index 0000000000..398ff72116 --- /dev/null +++ b/tools/build/eolstrip.c @@ -0,0 +1,366 @@ +/* + * eolstrip - strip white space from end of lines + * + * This program strips the white space from the end of every line in the + * specified program. + * + * usage: eolstrip [ -v ] [ arg ... ] files... + * -v -- verbose + * + * $Id$ + */ + +#define GETOPTARGS "vt" + +char *USAGE = "\ +usage: cklength [ -v ] [ arg ... ] files... \n\ + -v -- verbose\n\ + -t -- test only .. DO NOT OVERWRITE FILE!!!\n\ +\n\ +Strip the white space from the end of every line on the list of files.\n\ +"; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#ifndef VMS +#ifndef HAVE_STRERROR +extern int sys_nerr; +extern char *sys_errlist[]; + +#define strerror( _err ) \ + ((_err) < sys_nerr) ? sys_errlist [(_err)] : "unknown error" + +#else /* HAVE_STRERROR */ +char *strerror (); +#endif +#else /* VMS */ +char *strerror (int,...); +#endif + + +#define BUFFER_SIZE 2048 +#define MAX_PATH 2048 + +#define SUCCESS 0 +#define FAILURE -1 +#define Failed(x) (((int) (x)) == FAILURE) +#define TRUE 1 +#define FALSE 0 +#define STREQ(a,b) (strcmp(a,b) == 0) +#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + +/* + * Definitions for unsigned "ints"; especially for use in data structures + * that will be shared among (potentially) different cpu's (we punt on + * byte ordering problems tho) + */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +/* + * vars controlled by command line options + */ + +int verbose = FALSE; /* be verbose */ +int test_only = FALSE; /* test only */ + +extern char *optarg; /* getopt(3) control vars */ +extern int optind, opterr; + +char *progname; /* for error() */ + +int process(char *arg); +void error(int errn, ...); +long getparm(char *s, long min, long max, char *msg); + +#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */ +#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */ +#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */ + +#define stol(p) strtol(p, (char **) NULL, 0) +int Open(), Read(), Write(); + +int main( + int argc, + char **argv +) +{ + register int c; + int showusage = FALSE; /* usage error? */ + int rc = 0; + + /* + * figure out invocation leaf-name + */ + + if ((progname = strrchr(argv[0], '/')) == (char *) NULL) + progname = argv[0]; + else + progname++; + + argv[0] = progname; /* for getopt err reporting */ + + /* + * Check options and arguments. + */ + + opterr = 0; /* we'll report all errors */ + while ((c = getopt(argc, argv, GETOPTARGS)) != EOF) + switch (c) + { + case 't': /* toggle test only mode */ + test_only = ! test_only; + break; + + case 'v': /* toggle verbose */ + verbose = ! verbose; + break; + + case '?': + showusage = TRUE; + } + + if (showusage) + { + (void) fprintf(stderr, "%s", USAGE); + exit(1); + } + + /* + * traverse and process the arguments + */ + + for ( ; argv[optind]; optind++) + if (Failed(process(argv[optind]))) + rc = FAILURE; + + return rc; +} + + +/* + * process(arg) + */ + +int +process(char *arg) +{ + FILE *in; + FILE *out = (FILE *) 0; + char outname[ MAX_PATH ]; + char *bptr; + char buffer[ BUFFER_SIZE ]; + int length; + int line_number; + int rc = SUCCESS; /* succeed by default */ + + in = fopen( arg, "r" ); + if (!in) + error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg ); + + if ( !test_only ) { + sprintf( outname, "%s.eoltmp", arg ); + + out = fopen( outname, "w" ); + if (!out) + error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg ); + } + + if ( verbose ) + fprintf( stderr, "Processing %s\n", arg ); + + for ( line_number=1 ; ; line_number++ ) { + bptr = fgets( buffer, BUFFER_SIZE, in ); + if (!bptr) + break; + + /* + * Don't count the carriage return. + */ + + length = strlen( buffer ) - 1; + + if ( buffer[ length ] != '\n' ) + error(ERR_ERRNO|ERR_FATAL, "Line %d too long in %s\n", line_number, arg); + + while ( isspace( (unsigned char) buffer[ length ] ) ) + buffer[ length-- ] = '\0'; + + if ( test_only ) { + fprintf( stderr, "%s\n", arg ); + break; + } + + fprintf( out, "%s\n", buffer ); + } + + fclose( in ); + if ( !test_only ) { + fclose( out ); + rename( outname, arg ); + } + return rc; +} + +/* + * error(errn, arglist) + * report an error to stderr using printf(3) conventions. + * Any output is preceded by ': ' + * + * Uses ERR_FATAL bit to request exit(errn) + * ERR_ABORT to request abort() + * ERR_ERRNO to indicate use of errno instead of argument. + * + * If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its + * associated error message is appended to the output. + */ + +/*VARARGS*/ + +void +error(int error_flag, ...) +{ + va_list arglist; + register char *format; + int local_errno; + + extern int errno; + + (void) fflush(stdout); /* in case stdout/stderr same */ + + local_errno = error_flag & ~ERR_MASK; + if (error_flag & ERR_ERRNO) /* use errno? */ + local_errno = errno; + + va_start(arglist, error_flag); + format = va_arg(arglist, char *); + (void) fprintf(stderr, "%s: ", progname); + (void) vfprintf(stderr, format, arglist); + va_end(arglist); + + if (local_errno) + (void) fprintf(stderr, " (%s)\n", strerror(local_errno)); + else + (void) fprintf(stderr, "\n"); + + (void) fflush(stderr); + + if (error_flag & (ERR_FATAL | ERR_ABORT)) + { + if (error_flag & ERR_FATAL) + { + error(0, "fatal error, exiting"); + exit(local_errno ? local_errno : 1); + } + else + { + error(0, "fatal error, aborting"); + abort(); + } + } +} + +long +getparm(char *s, + long min, + long max, + char *msg) +{ + long val; + + if ( ! strchr("0123456789-", *s)) + { + error(ERR_FATAL, "'%s' is not a number", s); + return min; + } + + val = strtol(s, (char **) NULL, 0); + if ((val < min) || (val > max)) + { + if (min == max) + error(ERR_FATAL, "%s can only be %ld", s, min); + else + error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max); + } + + return val; +} + + +/* + * Open() + * Perform open(2), returning the file descriptor. Prints + * error message if open fails. + */ + +int +Open(char *file, + int oflag, + int mode) +{ + int O_fd; + + if (Failed(O_fd = open(file, oflag, mode))) + error( + ERR_ERRNO | ERR_FATAL, + "open('%s', 0x%x, 0%o) failed", file, oflag, mode + ); + + return O_fd; +} + +/* + * Read() + * Perform read(2); prints error message if fails. + */ + +int +Read(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = read(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "read(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} + +/* + * Write() + * Perform write(2); prints error message if fails. + */ + +int +Write(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = write(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "write(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} diff --git a/tools/build/install-if-change.in b/tools/build/install-if-change.in new file mode 100644 index 0000000000..b2f3cb04bb --- /dev/null +++ b/tools/build/install-if-change.in @@ -0,0 +1,142 @@ +#!@KSH@ -p +# +# Either bash or ksh will be ok for this; requires (( )) arithmetic +# (-p above just says to not parse $ENV file; makes it faster for +# those of us who set $ENV) +# +# install files if they have changed by running 'cmp', then 'install' +# as necessary. +# +# Optionally, can append a suffix before last existing suffix (if any) +# +# NOTE +# We avoid using typical install(1M) programs since they have +# large variability across systems and we also need to support ou +# -V option. +# So we just copy and chmod by hand. +# +# $Id$ +# + +progname=`basename $0` +#progname=${0##*/} # fast basename hack for ksh, bash + +USAGE=\ +"usage: $progname [ -vmV ] file [ file ... ] dest-directory-or-file + -v -- verbose + -V suffix -- suffix to append to targets (before any . suffix) + eg: -V _g would change 'foo' to 'foo_g' and + 'libfoo.a' to 'libfoo_g.a' + -m mode -- mode for new file(s)" + +fatal() { + if [ "$1" ] + then + echo $* >&2 + fi + echo "$USAGE" 1>&2 + exit 1 +} + +# +# process the options +# + +verbose="" +suffix="" +mode="" + +while getopts vm:V: OPT +do + case "$OPT" in + v) + verbose="yes";; + V) + eval suffix=$OPTARG;; + m) + mode="$OPTARG";; + *) + fatal + esac +done + +shiftcount=`expr $OPTIND - 1` +shift $shiftcount + +args=$* + +# +# Separate source file(s) from dest directory or file +# + +files="" +dest="" +for d in $args +do + files="$files $dest" + dest=$d +done + +if [ ! "$files" ] || [ ! "$dest" ] +then + fatal "missing files or invalid destination" +fi + +# +# Process the arguments +# + +targets="" +for f in $files +do + # leaf=`basename $f` + leaf=${f##*/} # fast basename hack for ksh, bash + + target=$dest + if [ -d $dest ] + then + # if we were given a suffix, then add it as appropriate + if [ "$suffix" ] + then + case $f in + *.*) + # leaf=`echo $leaf | + # /bin/sed "s/\([~\.]*\)\.\(.*\)$/\1$suffix.\2/"` + # ksh,bash hack for above sed script + leaf=${leaf%%.*}$suffix.${leaf#*.} + + [ "$verbose" = "yes" ] && + echo "$progname: $f will be installed as $leaf" + ;; + *) + leaf=$leaf$suffix;; + esac + fi + target=$target/$leaf + fi + + [ ! -r $f ] && fatal "can not read $f" + + if cmp -s $f $target + then + [ "$verbose" = "yes" ] && echo "'$f' not newer than '$target'" + else + [ "$verbose" = "yes" ] && echo "rm -f $target" + rm -f $target + echo "cp -p $f $target" + cp -p $f $target || exit 1 + targets="$targets $target" # keep list for chmod below + fi +done + +if [ "$mode" -a "$targets" ] +then + [ "$verbose" = "yes" ] && echo "chmod $mode $targets" + chmod $mode $targets +fi + +exit 0 + +# Local Variables: *** +# mode:ksh *** +# End: *** diff --git a/tools/build/multigen b/tools/build/multigen new file mode 100755 index 0000000000..06bfe65449 --- /dev/null +++ b/tools/build/multigen @@ -0,0 +1,173 @@ +#!/bin/sh + +# $Id$ + +version=0.1 +verbose=0 +target= +custom=0 +config=0 + +usage() +{ +program=`basename $0` +cat << EOF + +$program generates RTEMS custom/*.cfgs and config-files for gcc multilib +variants a target's gcc supports + +Usage: $program [options] + +Options: + --target=STRING target + --custom generate make/custom/*.cfg files + --config generate config scripts + --rtems=DIR use DIR as location of RTEMS source tree + -v, --verbose verbose + -h, --help Print this usage + --version Print version and exit + +Examples: +$program --config --target=sh-rtems --rtems=/usr/src/rtems-4.5.0 + Generates config scripts for all possible bare BSPs from all + valid multilib variants sh-rtems-gcc supports + +$program --custom --target=sh-rtems --rtems=/usr/src/rtems-4.5.0 + Generates /usr/src/rtems-4.5.0/make/custom/*.cfg files + for all possible bare BSPs from the multilib variants + sh-rtems-gcc supports + +Written by Ralf Corsepius +EOF +} + +while test $# -gt 0; do + case "$1" in + --rtems=*) + rtems_srcdir=`echo "$1" | sed -e 's%--rtems=\(.*\)%\1%g'` + ;; + --target=*) + target=`echo "$1" | sed -e 's%--target=\(.*\)%\1%g'` + ;; + -v|--verbose) + verbose=1 + ;; + --custom) + custom=1 + ;; + --config) + config=1 + ;; + --version) + echo `basename $0` version $version + exit 0 + ;; + -h|--help) + usage + exit 1 + ;; + *) + echo "unknown option $1" + usage + exit 1 + ;; + esac + shift +done + +if test $# -gt 0; then + echo "Invalid number of arguments" + exit 1 +fi + +if test x$target = x; then + echo "Missing required option:" + echo " --target" + exit 1 +fi + +if test x$rtems_srcdir = x; then + echo "Missing required option:" + echo " --rtems" + exit 1 +fi + +if test $config -eq 0 && test $custom -eq 0; then + echo "Missing required option:" + echo " --config" + echo " --custom" + echo " (At least one of these is required)" + exit 1 +fi + +if test ! -r $rtems_srcdir/VERSION; then + echo "Can't find rtems" + echo "Check value passed to --rtems=" + exit 1 +fi + +if test x$target != x ;then +target_prefix=$target- +fi + +# Check for CC +saved_IFS=$IFS; IFS=":" +for i in $PATH; do + if test -f $i/${target_prefix}gcc; then + CC=$i/${target_prefix}gcc + break + fi +done +IFS=$saved_IFS + +if test x$CC = x; then + echo "No valid gcc found" + exit 1 +fi +test $verbose -gt 0 && echo "Using $CC" + +for i in `${CC} --print-multi-lib 2>/dev/null`; do + dir=`echo $i | sed -e 's/;.*$//'` + case $dir in + .) f=$target + flags="" + ;; + *) f=`echo $target-$dir | sed -e 's%\/%-%g'` + flags=`echo $i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'` + ;; + esac + + if test $config -gt 0; then + cfg="rtems-config.$f" + test $verbose -gt 0 && echo "Generating: $cfg" + +cat << EOF > $cfg +#!/bin/sh + +${rtems_srcdir}/configure --target=$target \\ +'--enable-bare-cpu-cflags=$flags' \\ +--enable-rtemsbsp="bare" \\ +--enable-bare-cpu-model=NONE \\ +--disable-networking \\ +--disable-tests \\ +--enable-maintainer-mode +EOF + chmod +x $cfg + fi + + if test $custom -gt 0; then + cfg=${rtems_srcdir}/make/custom/bare-$f.cfg + test $verbose -gt 0 && echo "Generating: $cfg" +cat << EOF > $cfg +# Config file for the bare-$f BSP + +BARE_CPU_CFLAGS=$flags +BARE_CPU_MODEL=NONE + +include \$(RTEMS_ROOT)/make/custom/bare.cfg +EOF + + fi +done + +exit 0 diff --git a/tools/build/packhex.c b/tools/build/packhex.c new file mode 100644 index 0000000000..1e8edb615e --- /dev/null +++ b/tools/build/packhex.c @@ -0,0 +1,565 @@ + +/***** P A C K H E X . C ************************************************ + * + * Packhex is a hex-file compaction utility. It attempts to concatenate + * hex records to produce more size-efficient packaging. + * + * Limitations: Input files must be correctly formatted. This utility + * is not robust enough to detect hex-record formatting + * errors. + * + * Published: May 1993 Embedded Systems Programming magazine + * "Creating Faster Hex Files" + * + * URL: ESP magazine: http://www.embedded.com + * Source Code: ftp://ftp.mfi.com/pub/espmag/1993/pakhex.zip + * + * Author: Mark Gringrich + * + * Compiler: Microsoft C 6.0 + * cl /F 1000 packhex.c + * + * + * $Id$ + * + **************************************************************************/ + + +/* #define SMALLER_RECORDS */ +#ifdef SMALLER_RECORDS +#define MAX_LEN_S1_RECS 128 +#define MAX_LEN_S2_RECS 128 +#define MAX_LEN_S3_RECS 128 +#else +#define MAX_LEN_S1_RECS 252 +#define MAX_LEN_S2_RECS 251 +#define MAX_LEN_S3_RECS 250 +#endif + + +/*--------------------------------- includes ---------------------------------*/ + +#include +#include +#include + +#include "config.h" + +#ifndef VMS +#ifndef HAVE_STRERROR +extern int sys_nerr; +extern char *sys_errlist[]; + +#define strerror( _err ) \ + ((_err) < sys_nerr) ? sys_errlist [(_err)] : "unknown error" + +#else /* HAVE_STRERROR */ +char *strerror (); +#endif +#else /* VMS */ +char *strerror (int,...); +#endif + +#if defined(__unix__) && !defined(EXIT_FAILURE) +#define EXIT_FAILURE -1 +#define EXIT_SUCCESS 0 +#endif + +/*--------------------------------- defines ----------------------------------*/ + +#define YES 1 +#define MAX_LINE_SIZE 600 +#define EOS '\0' + + +/*---------------------------------- macros ----------------------------------*/ + +/* Convert ASCII hexadecimal digit to value. */ + +#define HEX_DIGIT( C ) ( ( ( ( C ) > '9' ) ? ( C ) + 25 : ( C ) ) & 0xF ) + + +/*--------------------------------- typedefs ---------------------------------*/ + +typedef unsigned char Boolean; +typedef unsigned char Uchar; +typedef unsigned int Uint; +typedef unsigned long Ulong; + +typedef struct /* Functions and constant returning Hex-record vital stats. */ +{ + Boolean ( *is_data_record )( char * ); + Ulong ( *get_address )( char * ); + Uint ( *get_data_count )( char * ); + const Uint max_data_count; + char *( *get_data_start )( char * ); + void ( *put_data_record )( Uint, Ulong, char * ); +} Rec_vitals; + + +/*--------------------------- function prototypes ----------------------------*/ + +Rec_vitals * identify_first_data_record( char *, int ); +Ulong get_ndigit_hex( char *, int ); + + +/*----------------------------- Intel Hex format -----------------------------*/ + +/* + * Intel Hex data-record layout + * + * :aabbbbccd...dee + * + * : - header character + * aa - record data byte count, a 2-digit hex value + * bbbb - record address, a 4-digit hex value + * cc - record type, a 2-digit hex value: + * "00" is a data record + * "01" is an end-of-data record + * "02" is an extended-address record + * "03" is a start record + * d...d - data (always an even number of chars) + * ee - record checksum, a 2-digit hex value + * checksum = 2's complement + * [ (sum of bytes: aabbbbccd...d) modulo 256 ] + */ + + +Boolean is_intel_data_rec( char * rec_str ) +{ + return( ( rec_str[ 0 ] == ':' ) && ( rec_str[ 8 ] == '0' ) ); +} + +Uint get_intel_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 1, 2 ) ); +} + +Ulong get_intel_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 3, 4 ) ); +} + +char * get_intel_rec_data_start( char * rec_str ) +{ + return( rec_str + 9 ); +} + +void put_intel_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = count + ( address >> 8 & 0xff ) + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + ":%02X%04lX00%s%02X\n", count, address, data_str, (~sum + 1) & 0xff + ); +} + + +Rec_vitals intel_hex = +{ + is_intel_data_rec, + get_intel_rec_address, + get_intel_rec_data_count, + 255, /* Maximum data bytes in a record. */ + get_intel_rec_data_start, + put_intel_data_rec +}; + + +/*------------------------- Motorola S1-record format ------------------------*/ + +/* + * Motorola S-record data-record layout + * + * Sabbc...cd...dee + * + * S - header character + * a - record type, a 1-digit value: + * "0" is a header record + * "1" is a 2-byte-address data record + * "2" is a 3-byte-address data record + * "3" is a 4-byte-address data record + * "7" is a 4-byte-address end-of-data record + * "8" is a 3-byte-address end-of-data record + * "9" is a 2-byte-address end-of-data record + * bb - record length in bytes, a 2-digit hex value + * (record length doesn't count the header/type + * chars and checksum byte) + * c...c - record address, a 4-, 6-, or 8-digit value, + * depending on record type + * d...d - data (always an even number of chars) + * ee - record checksum, a 2-digit hex value + * checksum = 1's complement + * [ (sum of all bytes: bbc..cd...d) modulo 256 ] + */ + +#define S1_COUNT_OFFSET 3 + + +Boolean is_moto_s1_data_rec( char * rec_str ) +{ + return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '1' ) ); +} + +Uint get_moto_s1_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S1_COUNT_OFFSET ); +} + +Ulong get_moto_s1_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 4, 4 ) ); +} + +char * get_moto_s1_rec_data_start( char * rec_str ) +{ + return( rec_str + 8 ); +} + +void put_moto_s1_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = S1_COUNT_OFFSET + count + + ( address >> 8 & 0xff ) + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + "S1%02X%04lX%s%02X\n", + count + S1_COUNT_OFFSET, address, data_str, ~sum & 0xff + ); +} + + +Rec_vitals motorola_s1_rec = +{ + is_moto_s1_data_rec, + get_moto_s1_rec_address, + get_moto_s1_rec_data_count, + MAX_LEN_S1_RECS, /* Maximum data bytes in a record. */ + get_moto_s1_rec_data_start, + put_moto_s1_data_rec +}; + + +/*------------------------- Motorola S2-record format ------------------------*/ + +#define S2_COUNT_OFFSET 4 + +Boolean is_moto_s2_data_rec( char * rec_str ) +{ + return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '2' ) ); +} + +Uint get_moto_s2_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S2_COUNT_OFFSET ); +} + +Ulong get_moto_s2_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 4, 6 ) ); +} + +char * get_moto_s2_rec_data_start( char * rec_str ) +{ + return( rec_str + 10 ); +} + +void put_moto_s2_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = S2_COUNT_OFFSET + count + ( address >> 16 & 0xff ) + + ( address >> 8 & 0xff ) + + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + "S2%02X%06lX%s%02X\n", + count + S2_COUNT_OFFSET, address, data_str, ~sum & 0xff + ); +} + + +Rec_vitals motorola_s2_rec = +{ + is_moto_s2_data_rec, + get_moto_s2_rec_address, + get_moto_s2_rec_data_count, + MAX_LEN_S2_RECS, /* Maximum data bytes in a record. */ + get_moto_s2_rec_data_start, + put_moto_s2_data_rec +}; + + +/*------------------------- Motorola S3-record format ------------------------*/ + +#define S3_COUNT_OFFSET 5 + +Boolean is_moto_s3_data_rec( char * rec_str ) +{ + return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '3' ) ); +} + +Uint get_moto_s3_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S3_COUNT_OFFSET ); +} + +Ulong get_moto_s3_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 4, 8 ) ); +} + +char * get_moto_s3_rec_data_start( char * rec_str ) +{ + return( rec_str + 12 ); +} + +void put_moto_s3_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = S3_COUNT_OFFSET + count + ( address >> 24 & 0xff ) + + ( address >> 16 & 0xff ) + + ( address >> 8 & 0xff ) + + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + "S3%02X%08lX%s%02X\n", + count + S3_COUNT_OFFSET, address, data_str, ~sum & 0xff + ); +} + + +Rec_vitals motorola_s3_rec = +{ + is_moto_s3_data_rec, + get_moto_s3_rec_address, + get_moto_s3_rec_data_count, + MAX_LEN_S3_RECS, /* Maximum data bytes in a record. */ + get_moto_s3_rec_data_start, + put_moto_s3_data_rec +}; + + +/*-------------------- Put your favorite hex format here ---------------------*/ + +/* + * * * * The following is a template for an additional hex format: * * * + * + * + * Boolean is_X_data_rec( char * rec_str ) {} + * + * Uint get_X_rec_data_count( char * rec_str ) {} + * + * Ulong get_X_rec_address( char * rec_str ) {} + * + * char * get_X_rec_data_start( char * rec_str ) {} + * + * void put_X_data_rec( Uint count, Ulong address, char * data_str ) {} + * + * Rec_vitals X_rec = + * { + * is_X_data_rec, + * get_X_rec_address, + * get_X_rec_data_count, + * MAXIMUM DATA BYTES IN A RECORD, + * get_X_rec_data_start, + * put_X_data_rec + * }; + * + */ + +/*----------------------------------------------------------------------------*/ + + +/* + * Put address of additional Rec_vitals structures + * in this array, before the NULL entry. + */ + +Rec_vitals *formats[] = +{ + &intel_hex, + &motorola_s1_rec, + &motorola_s2_rec, + &motorola_s3_rec, + ( Rec_vitals * ) NULL +}; + + +/**** main ***************************************************************** +* +* +* Expects: Nothing (no command-line parameters). +* +* Returns: Exit status (EXIT_SUCCESS or EXIT_FAILURE). +* +* Reads hex records on the standard input and attempts to +* splice adjacent data fields together. Results appear on +* the standard output. +* +*******************************************************************************/ + +int main( + int argc, + char **argv +) +{ + + char inbuff[ MAX_LINE_SIZE ], outbuff[ MAX_LINE_SIZE ]; + char *in_dptr, *out_dptr; + int d_total, d_count, d_excess, n; + int length; + Ulong in_rec_addr, out_rec_addr = 0; + Rec_vitals *rptr; + + + /* Sift through file until first hex record is identified. */ + + rptr = identify_first_data_record( inbuff, MAX_LINE_SIZE ); + if ( rptr == NULL ) + { + fputs( "No hex records found.\n", stderr ); + exit( EXIT_FAILURE ); + } + + + /* Attempt data-record splicing until end-of-file is reached. */ + d_total = 0; + for (;;) { + if ( rptr->is_data_record( inbuff ) == YES ) + { /* Input record is a data record. */ + d_count = rptr->get_data_count( inbuff ); + in_rec_addr = rptr->get_address( inbuff ); + in_dptr = rptr->get_data_start( inbuff ); + + if ( d_total == 0 || in_rec_addr != out_rec_addr + d_total ) + { /* Begin a new output record. */ + if ( d_total != 0 ) + rptr->put_data_record( d_total, out_rec_addr, outbuff ); + out_dptr = outbuff; + n = d_total = d_count; + out_rec_addr = in_rec_addr; + } + else if + ( ( d_excess = d_total + d_count - rptr->max_data_count ) > 0 ) + { /* Output a maximum-length record, then start a new record. */ + strncat( outbuff, in_dptr, 2 * ( d_count - d_excess ) ); + rptr->put_data_record( + rptr->max_data_count, out_rec_addr, outbuff + ); + in_dptr += 2 * ( d_count - d_excess ); + out_dptr = outbuff; + n = d_total = d_excess; + out_rec_addr += rptr->max_data_count; + } + else + { /* Append input record's data field with accumulated data. */ + out_dptr = outbuff + ( 2 * d_total ); + d_total += n = d_count; + } + strncpy( out_dptr, in_dptr, 2 * n ); + out_dptr[ 2 * n ] = EOS; + } + else + { /* Not a data record; + * flush accumulated data then echo non-data record. + */ + if ( d_total != 0 ) + { + rptr->put_data_record( d_total, out_rec_addr, outbuff ); + d_total = 0; + } + puts( inbuff ); + } + + inbuff[ MAX_LINE_SIZE - 1 ] = '\0'; + if ( !fgets( inbuff, MAX_LINE_SIZE, stdin ) ) + break; + if ( inbuff[ MAX_LINE_SIZE - 1 ] ) { + fprintf( stderr, "Input line too long" ); + exit( 1 ); + } + length = strlen(inbuff); + inbuff[length - 1] = '\0'; + + } + + + return ( EXIT_SUCCESS ); + +} + + +/**** identify_first_data_record ******************************************* +* +* Expects: Pointer to hex-record line buffer. +* +* Returns: Pointer to hex-record structure (NULL if no match found). +* +* Reads the standard input, line by line, searching for a valid +* record header character. If a valid header is found, a pointer +* to the hex-record's type structure is returned, otherwise NULL. +* +* The input-stream pointer is left pointing to the first valid hex record. +* +*******************************************************************************/ + +Rec_vitals * identify_first_data_record( char * buff_ptr, int max_length ) +{ + Rec_vitals ** ptr; + int length; + + + + for ( ;; ) { + + buff_ptr[ max_length - 1 ] = '\0'; + if ( !fgets( buff_ptr, max_length, stdin ) ) + break; + if ( buff_ptr[ max_length - 1 ] ) { + fprintf( stderr, "Input line too long" ); + exit( 1 ); + } + length = strlen(buff_ptr); + buff_ptr[length - 1] = '\0'; + + for ( ptr = formats ; *ptr != ( Rec_vitals * ) NULL ; ptr++ ) + if ( ( *ptr )->is_data_record( buff_ptr ) == YES ) + return( *ptr ); /* Successful return. */ + + puts( buff_ptr ); /* Echo non-hex-record line. */ + } + + return( ( Rec_vitals * ) NULL ); /* Unsuccessful return. */ +} + + +/**** get_ndigit_hex ******************************************************* +* +* Expects: Pointer to first ASCII hexadecimal digit, number of digits. +* +* Returns: Value of hexadecimal string as an unsigned long. +* +*******************************************************************************/ + +Ulong get_ndigit_hex( char * cptr, int digits ) +{ + Ulong value; + + for ( value = 0 ; --digits >= 0 ; cptr++ ) + value = ( value * 16L ) + HEX_DIGIT( *cptr ); + + return( value ); +} diff --git a/tools/build/rtems-bin2c.c b/tools/build/rtems-bin2c.c new file mode 100644 index 0000000000..4e6796aa38 --- /dev/null +++ b/tools/build/rtems-bin2c.c @@ -0,0 +1,291 @@ +/* + * bin2c.c + * + * convert a binary file into a C source array. + * + * THE "BEER-WARE LICENSE" (Revision 3.1415): + * sandro AT sigala DOT it wrote this file. As long as you retain this + * notice you can do whatever you want with this stuff. If we meet some + * day, and you think this stuff is worth it, you can buy me a beer in + * return. Sandro Sigala + * + * Subsequently modified by Joel Sherrill + * to add a number of capabilities not in the original. + * + * syntax: bin2c [-c] [-z] + * + * -c do NOT add the "const" keyword to definition + * -s add the "static" keywork to definition + * -v verbose + * -z terminate the array with a zero (useful for embedded C strings) + * + * examples: + * bin2c -c myimage.png myimage_png.cpp + * bin2c -z sometext.txt sometext_txt.cpp + * + */ + +#include +#include +#include +#include +#include + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +int useconst = 1; +int usestatic = 0; +int verbose = 0; +int zeroterminated = 0; +int createC = 1; +int createH = 1; + +int myfgetc(FILE *f) +{ + int c = fgetc(f); + if (c == EOF && zeroterminated) { + zeroterminated = 0; + return 0; + } + return c; +} + +void process(const char *ifname, const char *ofname) +{ + FILE *ifile, *ocfile, *ohfile; + char buf[PATH_MAX], *p; + char obasename[PATH_MAX]; + char ocname[PATH_MAX]; + char ohname[PATH_MAX]; + const char *cp; + size_t len; + + /* Error check */ + if ( !ifname || !ofname ) { + fprintf(stderr, "process has NULL filename\n"); + exit(1); + } + + strncpy( obasename, ofname, PATH_MAX ); + len = strlen( obasename ); + if ( len >= 2 ) { + if ( obasename[len-2] == '.' ) { + if ( (obasename[len-1] == 'c') || (obasename[len-1] == 'h') ) + obasename[len-2] = '\0'; + } + } + + sprintf( ocname, "%s.c", obasename ); + sprintf( ohname, "%s.h", obasename ); + + if ( verbose ) { + fprintf( + stderr, + "in file: %s\n" + "c file: %s\n" + "h file: %s\n", + ifname, + ocname, + ohname + ); + } + + /* Open input and output files */ + ifile = fopen(ifname, "rb"); + if (ifile == NULL) { + fprintf(stderr, "cannot open %s for reading\n", ifname); + exit(1); + } + + if ( createC ) { + ocfile = fopen(ocname, "wb"); + if (ocfile == NULL) { + fprintf(stderr, "cannot open %s for writing\n", ocname); + exit(1); + } + } + + if ( createH ) { + ohfile = fopen(ohname, "wb"); + if (ohfile == NULL) { + fprintf(stderr, "cannot open %s for writing\n", ohname); + exit(1); + } + } + + /* find basename */ + char *ifbasename = strdup(ifname); + ifbasename = basename(ifbasename); + + strcpy(buf, ifbasename); + for (p = buf; *p != '\0'; ++p) + if (!isalnum(*p)) + *p = '_'; + + if ( createC ) { + /* print C file header */ + fprintf( + ocfile, + "/*\n" + " * Declarations for C structure representing binary file %s\n" + " *\n" + " * WARNING: Automatically generated -- do not edit!\n" + " */\n" + "\n" + "#include \n" + "\n", + ifbasename + ); + + /* print structure */ + fprintf( + ocfile, + "%s%sunsigned char %s[] = {\n ", + ((usestatic) ? "static " : ""), + ((useconst) ? "const " : ""), + buf + ); + int c, col = 1; + while ((c = myfgetc(ifile)) != EOF) { + if (col >= 78 - 6) { + fprintf(ocfile, "\n "); + col = 1; + } + fprintf(ocfile, "0x%.2x, ", c); + col += 6; + + } + fprintf(ocfile, "\n};\n"); + + /* print sizeof */ + fprintf( + ocfile, + "\n" + "%s%ssize_t %s_size = sizeof(%s);\n", + ((usestatic) ? "static " : ""), + ((useconst) ? "const " : ""), + buf, + buf + ); + } /* createC */ + + /*****************************************************************/ + /****** END OF C FILE *****/ + /*****************************************************************/ + + if ( createH ) { + /* print H file header */ + fprintf( + ohfile, + "/*\n" + " * Extern declarations for C structure representing binary file %s\n" + " *\n" + " * WARNING: Automatically generated -- do not edit!\n" + " */\n" + "\n" + "#ifndef __%s_h\n" + "#define __%s_h\n" + "\n" + "#include \n" + "\n", + ifbasename, /* header */ + obasename, /* ifndef */ + obasename /* define */ + ); + + /* print structure */ + fprintf( + ohfile, + "extern %s%sunsigned char %s[];", + ((usestatic) ? "static " : ""), + ((useconst) ? "const " : ""), + buf + ); + /* print sizeof */ + fprintf( + ohfile, + "\n" + "extern %s%ssize_t %s_size;\n", + ((usestatic) ? "static " : ""), + ((useconst) ? "const " : ""), + buf + ); + + fprintf( + ohfile, + "\n" + "#endif\n" + ); + } /* createH */ + + /*****************************************************************/ + /****** END OF H FILE *****/ + /*****************************************************************/ + + fclose(ifile); + if ( createC ) { fclose(ocfile); } + if ( createH ) { fclose(ohfile); } +} + +void usage(void) +{ + fprintf( + stderr, + "usage: bin2c [-csvzCH] \n" + " is the binary file to convert\n" + " should not have a .c or .h extension\n" + "\n" + " -c - do NOT use const in declaration\n" + " -s - do use static in declaration\n" + " -v - verbose\n" + " -z - add zero terminator\n" + " -H - create c-header only\n" + " -C - create c-source file only\n" + ); + exit(1); +} + +int main(int argc, char **argv) +{ + while (argc > 3) { + if (!strcmp(argv[1], "-c")) { + useconst = 0; + --argc; + ++argv; + } else if (!strcmp(argv[1], "-s")) { + usestatic = 1; + --argc; + ++argv; + } else if (!strcmp(argv[1], "-v")) { + verbose = 1; + --argc; + ++argv; + } else if (!strcmp(argv[1], "-z")) { + zeroterminated = 1; + --argc; + ++argv; + } else if (!strcmp(argv[1], "-C")) { + createH = 0; + createC = 1; + --argc; + ++argv; + } else if (!strcmp(argv[1], "-H")) { + createC = 0; + createH = 1; + --argc; + ++argv; + } else { + usage(); + } + } + if (argc != 3) { + usage(); + } + + /* process( input_file, output_basename ) */ + process(argv[1], argv[2]); + return 0; +} + diff --git a/tools/build/search-id.sh b/tools/build/search-id.sh new file mode 100755 index 0000000000..a94d2d7cc9 --- /dev/null +++ b/tools/build/search-id.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# +# $Id$ +# + +find $1 -type f -a ! -name "*.scn" -a ! -name "bsp_specs" -a \ + -print > /tmp/$$.0 +find $1 -type f -a ! -name "*.scn" -a ! -name "bsp_specs" -a \ + -exec grep -l '$Id' {} \; > /tmp/$$.1 + +diff /tmp/$$.0 /tmp/$$.1 > /tmp/$$.2 + +grep "<" /tmp/$$.2 | sed 's/< //' >&1 + +rm -f /tmp/$$* diff --git a/tools/build/unhex.c b/tools/build/unhex.c new file mode 100644 index 0000000000..693049f465 --- /dev/null +++ b/tools/build/unhex.c @@ -0,0 +1,737 @@ +/* + * unhex + * convert a hex file to binary equivalent. If more than one file name + * is given, then the output will be logically concatenated together. + * stdin and stdout are defaults. Verbose will enable checksum output. + * + * Supported input formats are Intel hex, Motorola S records, and TI 'B' + * records. + * + * Intel hex input format is + * Byte + * 1 Colon : + * 2..3 Record length, eg: "20" + * 4..7 load address nibbles + * 8..9 record type: "00" (data) or "02" base addr + * 10..x data bytes in ascii-hex + * x+1..x+2 cksum (2's compl of (len+addr+data)) + * x+3 \n -- newline + * + * $Id$ + */ + +char *USAGE = "\ +usage: unhex [-va] [ -o file ] [ file [file ... ] ]\n\ + -v -- verbose\n\ + -a base -- 1st byte of output corresponds to this address\n\ + -l -- linear, just writes data out\n\ + -o file -- output file; must not be input file\n\ + -F k_bits -- \"holes\" in input will be filled with 0xFF's\n\ + up to \"k_bits\" * 1024 bits\n\ +"; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#ifndef VMS +#ifndef HAVE_STRERROR +extern int sys_nerr; +extern char *sys_errlist[]; + +#define strerror( _err ) \ + ((_err) < sys_nerr) ? sys_errlist [(_err)] : "unknown error" + +#else /* HAVE_STRERROR */ +char *strerror (); +#endif +#else /* VMS */ +char *strerror (int,...); +#endif + + +#define OK 0 +#define FAILURE (-1) +#define Failed(x) ((x) == FAILURE) +#define TRUE 1 +#define FALSE 0 +typedef char bool; +#define STREQ(a,b) (strcmp(a,b) == 0) + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +/* + * Pick out designated bytes + */ + +#define B0(x) ((x) & 0xff) +#define B1(x) B0((x) >> 8) +#define B2(x) B0((x) >> 16) +#define B3(x) B0((x) >> 24) + +typedef struct buffer_rec { + u32 dl_destaddr; + u32 dl_jumpaddr; + int dl_count; + u8 dl_buf[512]; +} buffer_rec; + +/* + * vars controlled by command line options + */ + +bool verbose = FALSE; /* be verbose */ +bool linear = FALSE; /* just write out linear data */ +char *outfilename = "-"; /* default output is stdout */ +u32 base = 0L; /* base address */ +u32 FFfill = 0L; /* how far to fill w 0xFF's */ + +extern char *optarg; /* getopt(3) control vars */ +extern int optind; + +char *progname; /* for error() */ + +void error(int errn, ...); +#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define ERR_FATAL (ERR_ERRNO / 2) /* error is fatal; no return */ +#define ERR_ABORT (ERR_ERRNO / 4) /* error is fatal; abort */ +#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */ + +#ifdef HAVE_STRTOUL +#define stol(p) strtoul(p, (char **) NULL, 0) +#else +#define stol(p) strtol(p, (char **) NULL, 0) +#endif + +int unhex(FILE *ifp, char *inm, FILE *ofp, char *onm); +int convert_Intel_records(FILE *ifp, char *inm, FILE *ofp, char *onm); +int convert_S_records(FILE *ifp, char *inm, FILE *ofp, char *onm); +int convert_TI_records(FILE *ifp, char *inm, FILE *ofp, char *onm); +void write_record(buffer_rec *tb, FILE *fp); +int getnibble(char **p); +int getbyte(char **p); +long getNbytes(char **p, int n); +void badformat(char *s, char *fname, char *msg); + +#define get1bytes(p) ((int) getbyte(p)) +#define get2bytes(p) ((int) getNbytes(p, 2)) +#define get3bytes(p) getNbytes(p, 3) +#define get4bytes(p) getNbytes(p, 4) + +char *BADADDR = "Invalid record address"; +char *BADLEN = "Invalid record length"; +char *BADBASE = "Bad base or starting address"; +char *BADFMT = "Unrecognized record type"; +char *BADDATA = "Invalid data byte"; +char *BADCSUM = "Invalid checksum"; +char *MISCSUM = "Checksum mismatch"; +char *BADTYPE = "Unrecognized record type"; +char *MISTYPE = "Incompatible record types"; + +int main( + int argc, + char **argv +) +{ + register int c; + bool showusage = FALSE; /* usage error? */ + int rc = 0; + FILE *outfp, *infp; + + /* + * figure out invocation leaf-name + */ + + if ((progname = strrchr(argv[0], '/')) == (char *) NULL) + progname = argv[0]; + else + progname++; + + argv[0] = progname; /* for getopt err reporting */ + + /* + * Check options and arguments. + */ + + progname = argv[0]; + while ((c = getopt(argc, argv, "F:a:o:vl")) != EOF) + switch (c) + { + case 'a': /* base address */ + base = stol(optarg); + break; + + case 'l': /* linear output */ + linear = TRUE; + break; + + case 'v': /* toggle verbose */ + verbose = ! verbose; + break; + + case 'o': /* output file */ + outfilename = optarg; + break; + + case 'F': /* 0xFF fill amount (bytes) */ + FFfill = stol(optarg) * 1024L / 8L; + break; + + case '?': + showusage = TRUE; + } + + if (showusage) + { + (void) fprintf(stderr, "%s", USAGE); + exit(1); + } + + if (linear && (base != 0)) + { + error(0, "-l and -a may not be specified in combination"); + exit(1); + } + + if (STREQ(outfilename, "-")) + { + outfp = stdout; + outfilename = "stdout"; + } + else + if ((outfp = fopen(outfilename, "w")) == (FILE *) NULL) + { + error(-1, "couldn't open '%s' for output", outfilename); + exit(1); + } + + /* + * Now process the input files (or stdin, if none specified) + */ + + if (argv[optind] == (char *) NULL) /* just stdin */ + exit(unhex(stdin, "stdin", outfp, outfilename)); + else + for (; (optarg = argv[optind]); optind++) + { + if (STREQ(optarg, "-")) + rc += unhex(stdin, "stdin", outfp, outfilename); + else + { + if ((infp = fopen(optarg, "r")) == (FILE *) NULL) + { + error(-1, "couldn't open '%s' for input", optarg); + exit(1); + } + rc += unhex(infp, optarg, outfp, outfilename); + } + } + + return(rc); +} + +u16 filesum; + +int +unhex(FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + int c; + + filesum = 0; + + /* + * Make sure holes will be filled with 0xFF's if requested. We + * do this the easy way by just filling the file with FF's before + * getting started. To do it more optimally would be quite a bit + * more difficult since the user can skip around as much as he/she + * likes in the input hex file addressing. + * + * We'll clean this up later (after this program has run) with + * 'stripffs' + */ + + if (FFfill) + { + (void) fseek(ofp, 0, 0); + for (c = FFfill; c > 0; c--) + (void) fputc(0xFF, ofp); + } + + /* + * Read the first char from file and determine record types + */ + + if ((c = getc(ifp)) != EOF) + { + ungetc(c, ifp); + switch(c) + { + case 'S': + convert_S_records(ifp, inm, ofp, onm); + break; + + case ':': + convert_Intel_records(ifp, inm, ofp, onm); + break; + + case '9': + case 'B': + convert_TI_records(ifp, inm, ofp, onm); + break; + + default: + { + char tmp[2]; + tmp[0] = c; tmp[1] = 0; + badformat(tmp, inm, BADFMT); + } + } + } + + if (verbose) + fprintf(stderr, "'%s' checksum is 0x%04x\n", inm, filesum); + + return 0; +} + +int +convert_Intel_records( + FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + char buff[512]; + char *p; + u8 cksum; + int incksum; + int c; + int rectype; /* record type */ + int len; /* data length of current line */ + u32 addr; + u32 base_address = 0; + bool endrecord = FALSE; + buffer_rec tb; + + while ( ! endrecord && (fgets(buff, sizeof(buff), ifp))) + { + p = &buff[0]; + + if (p[strlen(p)-1] == '\n') /* get rid of newline */ + p[strlen(p)-1] = '\0'; + + if (p[strlen(p)-1] == '\r') /* get rid of any CR */ + p[strlen(p)-1] = '\0'; + + tb.dl_count = 0; + + if (*p != ':') + badformat(p, inm, BADFMT); + p++; + + if ((len = getbyte(&p)) == -1) /* record len */ + badformat(buff, inm, BADLEN); + + if ((addr = get2bytes(&p)) == -1L) /* record addr */ + badformat(buff, inm, BADADDR); + + rectype = getbyte(&p); + + cksum = len + B0(addr) + B1(addr) + rectype; + + switch (rectype) + { + case 0x00: /* normal data record */ + tb.dl_destaddr = base_address + addr; + while (len--) + { + if ((c = getbyte(&p)) == -1) + badformat(buff, inm, BADDATA); + cksum += c; + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + } + break; + + case 0x01: /* execution start address */ + base_address = addr; + endrecord = TRUE; + break; + + case 0x02: /* new base */ + if ((base_address = get2bytes(&p)) == -1L) + badformat(buff, inm, BADBASE); + cksum += B0(base_address) + B1(base_address); + base_address <<= 4; + break; + + case 0x03: /* seg/off execution start address */ + { + u32 seg, off; + + seg = get2bytes(&p); + off = get2bytes(&p); + if ((seg == -1L) || (off == -1L)) + badformat(buff, inm, BADADDR); + + cksum += B0(seg) + B1(seg) + B0(off) + B1(off); + + tb.dl_jumpaddr = (seg << 4) + off; + break; + } + + default: + error(0, "unknown Intel-hex record type: 0x%02x", rectype); + badformat(buff, inm, BADTYPE); + } + + /* + * Verify checksums are correct in file. + */ + + cksum = (-cksum) & 0xff; + if ((incksum = getbyte(&p)) == -1) + badformat(buff, inm, BADCSUM); + if (((u8) incksum) != cksum) + badformat(buff, inm, MISCSUM); + + if (tb.dl_count) + write_record(&tb, ofp); + } + return 0; +} + +int +convert_S_records( + FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + char buff[512]; + char *p; + u8 cksum; + int incksum; + int c; + int len; /* data length of current line */ + int rectype; /* record type */ + u32 addr; + bool endrecord = FALSE; + buffer_rec tb; + + while ( ! endrecord && (fgets(buff, sizeof(buff), ifp))) + { + p = &buff[0]; + + if (p[strlen(p)-1] == '\n') /* get rid of newline */ + p[strlen(p)-1] = '\0'; + + if (p[strlen(p)-1] == '\r') /* get rid of any CR */ + p[strlen(p)-1] = '\0'; + + tb.dl_count = 0; + + if (*p != 'S') + badformat(p, inm, BADFMT); + p++; + + if ((rectype = getnibble(&p)) == -1) /* record type */ + badformat(buff, inm, BADTYPE); + + if ((len = getbyte(&p)) == -1) /* record len */ + badformat(buff, inm, BADLEN); + cksum = len; + + switch (rectype) + { + case 0x00: /* comment field, ignored */ + goto write_it; + + case 0x01: /* data record, 16 bit addr */ + if ((addr = get2bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + len -= 3; + goto doit; + + case 0x02: /* ... 24 bit addr */ + if ((addr = get3bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + len -= 4; + goto doit; + + case 0x03: /* ... 32 bit addr */ + if ((addr = get4bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + len -= 5; + doit: + cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr); + + tb.dl_destaddr = addr; + while (len--) + { + if ((c = getbyte(&p)) == -1) + badformat(buff, inm, BADDATA); + cksum += c; + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + } + break; + + case 0x07: /* 32 bit end record */ + if ((addr = get4bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + goto end_rec; + + case 0x08: /* 24 bit end record */ + if ((addr = get3bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + goto end_rec; + + case 0x09: /* 16 bit end record */ + if ((addr = get2bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + +end_rec: + cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr); + tb.dl_jumpaddr = addr; + break; + + default: + error(0, "unknown Motorola-S record type: 0x%02x", rectype); + badformat(buff, inm, BADTYPE); + break; + } + + /* + * Verify checksums are correct in file. + */ + + cksum = (~cksum) & 0xff; + if ((incksum = getbyte(&p)) == -1) + badformat(buff, inm, BADCSUM); + if (((u8) incksum) != cksum) + badformat(buff, inm, MISCSUM); + +write_it: + if (tb.dl_count) + write_record(&tb, ofp); + } + return 0; +} + +int +convert_TI_records( + FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + char buff[512]; + char *p; + int c; + bool endrecord = FALSE; + bool eol; + buffer_rec tb; + + while ( ! endrecord && (fgets(buff, sizeof(buff), ifp))) + { + if (p[strlen(p)-1] == '\n') /* get rid of newline */ + p[strlen(p)-1] = '\0'; + + if (p[strlen(p)-1] == '\r') /* get rid of any CR */ + p[strlen(p)-1] = '\0'; + + tb.dl_count = 0; + + p = &buff[0]; + eol = FALSE; + while ( ! eol && ! endrecord) + { + switch (*p++) + { + case '9': + if (tb.dl_count) + write_record(&tb, ofp); + tb.dl_destaddr = get2bytes(&p); + break; + + case 'B': + c = getbyte(&p); + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + c = getbyte(&p); + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + break; + + case 'F': + eol = TRUE; + break; + + case ':': + endrecord = TRUE; + break; + + default: + badformat(p, inm, BADFMT); + } + } + if (tb.dl_count) + write_record(&tb, ofp); + } + return 0; +} + +void +write_record(buffer_rec *tb, + FILE *fp) +{ + if ( ! linear) + { + if (tb->dl_destaddr < base) + error(ERR_FATAL, "record at address 0x%x precedes base of 0x%x", + tb->dl_destaddr, base); + (void) fseek(fp, tb->dl_destaddr - base, 0); + } + + (void) fwrite(tb->dl_buf, tb->dl_count, 1, fp); + tb->dl_destaddr += tb->dl_count; + tb->dl_count = 0; +} + +int +getnibble(char **p) +{ + register int val; + + **p = toupper(**p); + switch (**p) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + val = **p - '0'; + break; + + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + val = 10 + (**p - 'A'); + break; + + default: + return(-1); + } + *p += 1; + + return(val & 0x0f); +} + +int +getbyte(char **p) +{ + int n0, n1; + + if ((n0 = getnibble(p)) == -1) + return(-1); + if ((n1 = getnibble(p)) == -1) + return(-1); + + return(((n0 << 4) + n1) & 0xff); +} + +long +getNbytes(char **p, + int n) +{ + int t; + u32 val = 0; + + while (n--) + { + if ((t = getbyte(p)) == -1) + return(-1L); + val <<= 8; + val += t; + } + + return(val); +} + +void +badformat(char *s, + char *fname, + char *msg) +{ + if (s[strlen(s)-1] == '\n') /* get rid of newline */ + s[strlen(s)-1] = '\0'; + error(0, "line '%s'::\n\tfrom file '%s'; %s", s, fname, msg); + exit(1); +} + +/* + * error(errn, arglist) + * report an error to stderr using printf(3) conventions. + * Any output is preceded by ': ' + * + * Uses ERR_EXIT bit to request exit(errn) + * ERR_ABORT to request abort() + * ERR_ERRNO to indicate use of errno instead of argument. + * + * If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its + * associated error message is appended to the output. + */ + +/*VARARGS*/ + +void +error(int error_flag, ...) +{ + va_list arglist; + register char *format; + int local_errno; + + extern int errno; + + (void) fflush(stdout); /* in case stdout/stderr same */ + + local_errno = error_flag & ~ERR_MASK; + if (error_flag & ERR_ERRNO) /* use errno? */ + local_errno = errno; + + va_start(arglist, error_flag); + format = va_arg(arglist, char *); + (void) fprintf(stderr, "%s: ", progname); + (void) vfprintf(stderr, format, arglist); + va_end(arglist); + + if (local_errno) + (void) fprintf(stderr, " (%s)\n", strerror(local_errno)); + else + (void) fprintf(stderr, "\n"); + + (void) fflush(stderr); + + if (error_flag & (ERR_FATAL | ERR_ABORT)) + { + if (error_flag & ERR_FATAL) + { + error(0, "fatal error, exiting"); + exit(local_errno ? local_errno : 1); + } + else + { + error(0, "fatal error, aborting"); + abort(); + } + } +} diff --git a/tools/cpu/.cvsignore b/tools/cpu/.cvsignore new file mode 100644 index 0000000000..bfdfd995be --- /dev/null +++ b/tools/cpu/.cvsignore @@ -0,0 +1,14 @@ +aclocal.m4 +autom4te*.cache +config.cache +config.guess +config.log +config.status +config.sub +configure +depcomp +install-sh +Makefile +Makefile.in +missing +mkinstalldirs diff --git a/tools/cpu/ChangeLog b/tools/cpu/ChangeLog new file mode 100644 index 0000000000..41cb404581 --- /dev/null +++ b/tools/cpu/ChangeLog @@ -0,0 +1,123 @@ +2011-02-02 Ralf Corsépius + + * configure.ac: Require autoconf-2.68, automake-1.11.1. + +2006-12-02 Ralf Corsépius + + * configure.ac: New BUG-REPORT address. + +2006-10-17 Ralf Corsépius + + * configure.ac: Require autoconf-2.60. Require automake-1.10. + +2006-08-09 Kolja Waschk + + * configure.ac: New port to Altera NIOS II. + * nios2/.cvsignore, nios2/Makefile.am, nios2/README, nios2/bridges.c, + nios2/bridges.h, nios2/clocks.c, nios2/clocks.h, nios2/configure.ac, + nios2/devices.c, nios2/devices.h, nios2/nios2gen.c, nios2/output.c, + nios2/output.h, nios2/ptf.c, nios2/ptf.h: New files. + +2004-09-24 Ralf Corsepius + + * configure.ac: Require automake > 1.9. + +2004-09-24 Ralf Corsepius + + * configure.ac: Remove RTEMS_CPU_SUBDIRS. + +2004-02-04 Ralf Corsepius + + * Makefile.am: DIST_SUBDIRS = @subdirs@. + +2003-12-12 Ralf Corsepius + + * configure.ac: Require automake >= 1.8, autoconf >= 2.59. + +2003-09-26 Joel Sherrill + + * Makefile.am: Obsoleting HP PA-RISC port. + +2003-09-26 Joel Sherrill + + * hppa1.1/.cvsignore, hppa1.1/ChangeLog, hppa1.1/Makefile.am, + hppa1.1/configure.ac, hppa1.1/genoffsets.c: Removed. + +2003-08-11 Ralf Corsepius + + * configure.ac: Use rtems-bugs@rtems.com as bug report email address. + +2003-03-06 Ralf Corsepius + + * configure.ac: Remove AC_CONFIG_AUX_DIR. + +2003-02-11 Ralf Corsepius + + * configure.ac: AM_INIT_AUTOMAKE([1.7.2]). + +2003-02-11 Ralf Corsepius + + * configure.ac: AC_PREREQ(2.57). + +2002-10-21 Ralf Corsepius + + * .cvsignore: Reformat. + Add autom4te*cache. + Remove autom4te.cache. + +2001-04-03 Joel Sherrill + + * sh/COPYING: Readded. Deleting this violated GPL on shgen. + + +2001-04-02 Joel Sherrill + + * sh/COPYING: Deleted. + +2001-04-02 Joel Sherrill + + * sh/Makefile.am: Use "./shgen" not "shgen" so current directory + does not have to be in the PATH. + +2001-04-02 Joel Sherrill + + * Makefile.am: Remove unix from DIST_SUBDIRS. + +2001-03-29 Joel Sherrill + + * Per PR150, unix directory and contents removed. + * unix/, unix/ChangeLog, unix/Makefile.am, unix/configure.ac, + unix/gensize.c: Deleted. + +2002-03-27 Ralf Corsepius + + * configure.ac: + AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS). + AM_INIT_AUTOMAKE([no-define foreign 1.6]). + * Makefile.am: Remove AUTOMAKE_OPTIONS. + +2001-10-11 Ralf Corsepius + + * .cvsignore: Add autom4te.cache for autoconf > 2.52. + * configure.in: Remove. + * configure.ac: New file, generated from configure.in by autoupdate. + +2001-10-09 Ralf Corsepius + + * configure.in: AC_PREREQ(2.52), apply RTEMS_CPU_SUBDIRS. + +2000-11-09 Ralf Corsepius + + * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS. + +2000-11-02 Ralf Corsepius + + * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal. + +2000-10-30 Ralf Corsepius + + * Makefile.am: Switch to GNU-canonicalized autoconf macros. + +2000-08-10 Joel Sherrill + + * ChangeLog: New file. diff --git a/tools/cpu/Makefile.am b/tools/cpu/Makefile.am new file mode 100644 index 0000000000..43b1da1524 --- /dev/null +++ b/tools/cpu/Makefile.am @@ -0,0 +1,12 @@ +## +## $Id$ +## + +ACLOCAL_AMFLAGS = -I ../../aclocal + +SUBDIRS = @subdirs@ + +DIST_SUBDIRS = @subdirs@ + +include $(top_srcdir)/../../automake/subdirs.am +include $(top_srcdir)/../../automake/host.am diff --git a/tools/cpu/configure.ac b/tools/cpu/configure.ac new file mode 100644 index 0000000000..f5ae63bfbf --- /dev/null +++ b/tools/cpu/configure.ac @@ -0,0 +1,28 @@ +## Process this file with autoconf to produce a configure script. +## +## $Id$ + +AC_PREREQ([2.68]) +AC_INIT([rtems-tools-cpu],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([generic]) +RTEMS_TOP(../..) + +RTEMS_CANONICAL_TARGET_CPU + +AM_INIT_AUTOMAKE([no-define foreign 1.11.1]) +AM_MAINTAINER_MODE + +RTEMS_PATH_KSH + +RTEMS_TOOLPATHS +AC_SUBST(program_prefix) + +AC_CONFIG_SUBDIRS(generic) +case "$RTEMS_CPU" in +sh ) AC_CONFIG_SUBDIRS(sh);; +nios2 ) AC_CONFIG_SUBDIRS(nios2);; +esac + +# Explicitly list all Makefiles here +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/tools/cpu/generic/.cvsignore b/tools/cpu/generic/.cvsignore new file mode 100644 index 0000000000..2b8cbd9acc --- /dev/null +++ b/tools/cpu/generic/.cvsignore @@ -0,0 +1,15 @@ +aclocal.m4 +autom4te*.cache +config.cache +config.guess +config.log +config.status +config.sub +configure +depcomp +install-sh +Makefile +Makefile.in +missing +mkinstalldirs +size_rtems diff --git a/tools/cpu/generic/ChangeLog b/tools/cpu/generic/ChangeLog new file mode 100644 index 0000000000..1651f3e3d5 --- /dev/null +++ b/tools/cpu/generic/ChangeLog @@ -0,0 +1,78 @@ +2011-02-02 Ralf Corsépius + + * configure.ac: Require autoconf-2.68, automake-1.11.1. + +2006-12-02 Ralf Corsépius + + * configure.ac: New BUG-REPORT address. + +2006-10-17 Ralf Corsépius + + * configure.ac: Require autoconf-2.60. Require automake-1.10. + +2004-09-24 Ralf Corsepius + + * configure.ac: Require automake > 1.9. + +2003-12-12 Ralf Corsepius + + * configure.ac: Require automake >= 1.8, autoconf >= 2.59. + +2003-12-12 Ralf Corsepius + + * Makefile.am: Cosmetics. + +2003-09-04 Joel Sherrill + + * size_rtems.in: URL for license changed. + +2003-08-11 Ralf Corsepius + + * configure.ac: Use rtems-bugs@rtems.com as bug report email address. + +2003-03-06 Ralf Corsepius + + * configure.ac: Remove AC_CONFIG_AUX_DIR. + +2003-02-11 Ralf Corsepius + + * configure.ac: AM_INIT_AUTOMAKE([1.7.2]). + +2003-02-11 Ralf Corsepius + + * configure.ac: AC_PREREQ(2.57). + +2002-10-21 Ralf Corsepius + + * .cvsignore: Reformat. + Add autom4te*cache. + Remove autom4te.cache. + +2002-03-27 Ralf Corsepius + + * configure.ac: + AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS). + AM_INIT_AUTOMAKE([no-define foreign 1.6]). + * Makefile.am: Remove AUTOMAKE_OPTIONS. + +2001-10-11 Ralf Corsepius + + * .cvsignore: Add autom4te.cache for autoconf > 2.52. + * configure.in: Remove. + * configure.ac: New file, generated from configure.in by autoupdate. + +2000-11-09 Ralf Corsepius + + * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS. + +2000-11-02 Ralf Corsepius + + * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal. + +2000-10-30 Ralf Corsepius + + * Makefile.am: Switch to GNU-canonicalized autoconf macros. + +2000-08-10 Joel Sherrill + + * ChangeLog: New file. diff --git a/tools/cpu/generic/Makefile.am b/tools/cpu/generic/Makefile.am new file mode 100644 index 0000000000..8f4d18658f --- /dev/null +++ b/tools/cpu/generic/Makefile.am @@ -0,0 +1,9 @@ +## +## $Id$ +## + +ACLOCAL_AMFLAGS = -I ../../../aclocal + +noinst_SCRIPTS = size_rtems + +include $(top_srcdir)/../../../automake/host.am diff --git a/tools/cpu/generic/configure.ac b/tools/cpu/generic/configure.ac new file mode 100644 index 0000000000..0ac6687587 --- /dev/null +++ b/tools/cpu/generic/configure.ac @@ -0,0 +1,23 @@ +## Process this file with autoconf to produce a configure script. +## +## $Id$ + +AC_PREREQ([2.68]) +AC_INIT([rtems-tools-cpu-generic],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([size_rtems.in]) +RTEMS_TOP(../../..) + +RTEMS_CANONICAL_TARGET_CPU + +AM_INIT_AUTOMAKE([no-define foreign 1.11.1]) +AM_MAINTAINER_MODE + +RTEMS_PATH_KSH + +RTEMS_TOOLPATHS +AC_SUBST(program_prefix) + +# Explicitly list all Makefiles here +AC_CONFIG_FILES([Makefile +size_rtems]) +AC_OUTPUT diff --git a/tools/cpu/generic/size_rtems.in b/tools/cpu/generic/size_rtems.in new file mode 100644 index 0000000000..93fa1d59c6 --- /dev/null +++ b/tools/cpu/generic/size_rtems.in @@ -0,0 +1,284 @@ +#!@KSH@ -p +# +# size_rtems +# +# This script gathers information related to the size of RTEMS +# using the GNU "size" command. +# +# This script operates by summing up the sizes of the various +# object files which constitute a particular configuration of +# RTEMS. This size information is gathered for placement in the +# brochure flyers and supplement manuals. +# +# NOTE: The concept of the minimum executive size is buried in this script. +# +# COPYRIGHT (c) 1989-1999. +# On-Line Applications Research Corporation (OAR). +# +# The license and distribution terms for this file may be +# found in the file LICENSE in this distribution or at +# http://www.rtems.com/license/LICENSE. +# +# $Id$ +# + +target=@target@ +program_prefix=@program_prefix@ + +gnusize=${program_prefix}size + +# check usage +if [ $# -ne 2 ] ; then + echo usage ${0}: bsp object_directory + exit 1 +fi + +bsp=$1 +board=$1 +ARCH=$2 + +cpu=`echo $target | sed -e 's/-.*//'` + +case $target in + sparc-sun-solaris*) + rtems_cpu=unix + bsp=solaris2 + echo Not supported on unix port. + exit 0 + ;; + i[34567]86-pc-linux-gnu) + echo linux + rtems_cpu=unix + bsp=linux1 + echo Not supported on unix port. + exit 0 + ;; + i[34567]86-unknown-freebsd2.[12]*) + echo freebsd + rtems_cpu=unix + bsp=freebsd2 + echo Not supported on unix port. + exit 0 + ;; + *-rtems*) + cpu=`echo $target | sed -e 's/-.*//'` + rtems_cpu=$cpu + ;; + *) + echo unknown target $target + exit 1 + ;; +esac + +case $ARCH in + *debug*) VARIANT=debug ;; + *profile*) VARIANT=profile ;; + *) VARIANT=optimized;; +esac + +echo +echo Size Information for the Following Configuration: +echo CPU: ${cpu} +echo BSP: ${board} +echo VARIANT: ${VARIANT} +echo + + +# +# KLUDGE to figure out at runtime how to echo a line without a +# newline. +# +count=`echo "\\c" | wc -c` +if [ ${count} -ne 0 ] ; then + EARG="-n" + EOL="" +else + EARG="" + EOL="\\c" +fi + +if [ ! -d ../${board} ] ; then + echo "${board} does not exist ... is the current directory the build directory?" + exit 1 +fi + +#DIRLIST -- so greps for DIRLIST will find this file +CPUOBJ=exec/score/cpu/${rtems_cpu}/wrap/${ARCH} +COREOBJ=exec/score/src/${ARCH} +RTEMSOBJ=exec/rtems/src/${ARCH} +SAPIOBJ=exec/sapi/src/${ARCH} +OPTOBJ=exec/rtems/optman/${ARCH} + +# XXX These have been split up +MANLIST=" \ +${RTEMSOBJ}/clockget.o \ +${RTEMSOBJ}/clockset.o \ +${RTEMSOBJ}/clocktick.o \ +${RTEMSOBJ}/dpmem.o \ +${RTEMSOBJ}/event.o \ +${RTEMSOBJ}/intr.o \ +${RTEMSOBJ}/msg.o \ +${RTEMSOBJ}/part.o \ +${RTEMSOBJ}/ratemon.o \ +${RTEMSOBJ}/region.o \ +${RTEMSOBJ}/sem.o \ +${RTEMSOBJ}/signal.o \ +${RTEMSOBJ}/tasks.o \ +${RTEMSOBJ}/timer.o \ +${SAPIOBJ}/debug.o \ +${SAPIOBJ}/extension.o \ +${SAPIOBJ}/fatal.o \ +${SAPIOBJ}/exinit.o \ +${SAPIOBJ}/io.o \ +${SAPIOBJ}/rtemsapi.o \ +" + +if [ -r ${RTEMSOBJ}/mp.o ] ; then + MPLIST="\ + ${RTEMSOBJ}/mp.o ${RTEMSOBJ}/eventmp.o \ + ${COREOBJ}/mpci.o ${RTEMSOBJ}/msgmp.o ${COREOBJ}/objectmp.o \ + ${RTEMSOBJ}/partmp.o ${RTEMSOBJ}/regionmp.o ${RTEMSOBJ}/semmp.o \ + ${RTEMSOBJ}/signalmp.o ${RTEMSOBJ}/taskmp.o ${COREOBJ}/threadmp.o \ + " + + MPOBJLIST=${OPTOBJ}/no-mp.rel +fi + +OPTMANLIST="\ +${OPTOBJ}/no-dpmem.rel \ +${OPTOBJ}/no-event.rel \ +${MPOBJLIST} \ +${OPTOBJ}/no-msg.rel \ +${OPTOBJ}/no-part.rel \ +${OPTOBJ}/no-region.rel \ +${OPTOBJ}/no-rtmon.rel \ +${OPTOBJ}/no-sem.rel \ +${OPTOBJ}/no-signal.rel \ +${OPTOBJ}/no-timer.rel \ +" +REQMANLIST="\ +${SAPIOBJ}/exinit.o \ +${RTEMSOBJ}/tasks.o \ +${RTEMSOBJ}/intr.o \ +${SAPIOBJ}/fatal.o \ +" +# XXX parts of these have been split up +CORELIST=" \ +${COREOBJ}/apiext.o ${COREOBJ}/chain.o \ +${COREOBJ}/coremsg.o ${COREOBJ}/coremutex.o ${COREOBJ}/coresem.o \ +${COREOBJ}/heap.o ${COREOBJ}/interr.o \ +${COREOBJ}/isr.o \ +${COREOBJ}/object.o \ +${SAPIOBJ}/rtemsapi.o \ +${COREOBJ}/thread.o ${COREOBJ}/threadq.o ${COREOBJ}/tod.o \ +${COREOBJ}/userext.o \ +${COREOBJ}/watchdog.o ${COREOBJ}/wkspace.o \ +" + +CPULIST="\ +${CPUOBJ}/rtems-cpu.rel \ +" + +# check directories +for i in ${EXECOBJ} ${CPUOBJ} ${OPTOBJ} +do + if [ ! -d ${i} ] ; then + echo "${i} does not exist ... is RTEMS compiled and installed?" + exit 1 + fi +done + +for i in ${MANLIST} ${MPLIST} ${OPTMANLIST} ${REQMANLIST} ${CORELIST} ${CPULIST} +do + if [ ! -r ${i} ] ; then + echo ${i} does not exist ... is RTEMS compiled and installed? + exit 1 + fi +done + +# "rips" a line of gsize's output and prints size, data, bss +parse_size() +{ + echo $1 $2 $3 +} + +# prepares a list of code, data, bss sizes for a directory +sizedir() +{ + ${gnusize} $* | sed -e '1,1d' | + while read line + do + parse_size ${line} + done +} + +# adds the numbers passed on the command line +addit() +{ + sumx=0 + for x in $* + do + sumx=`expr $sumx + $x` + done + echo $sumx +} + +# adds a column from the output of sizedir +addsizes() +{ + # dc version is not portable enough -- It can be left out during + # installing linux and may not be available on non-UNIX hosts. + #cut -d' ' -f${2} ${1} | sed -e '2,$s/$/ + /' -e '$,$s/$/ p/' | dc + + # This may not be as fast but it is probably more portable. + addit `cut -d' ' -f${2} ${1}` +} + +# calculates total size of a directory and prints report line +size_files() +{ + trap "rm -f /tmp/size.$$ ; exit 1" 2 3 + + for file in $* + do + parse_size `${gnusize} $file | sed -e '/text/d'` + done >/tmp/size.$$ + + code=`cat /tmp/size.$$ | addsizes 1` + data=`cat /tmp/size.$$ | addsizes 2` + bss=` cat /tmp/size.$$ | addsizes 3` + echo "${code} ${data} ${bss}" + rm /tmp/size.$$ +} + +echo +echo " RTEMS SIZE REPORT" +echo +echo " CODE DATA BSS" +echo " ==================" +echo ${EARG} "MANAGERS: " ${EOL} ; size_files $MANLIST $MPLIST +echo ${EARG} "CORE : " ${EOL} ; size_files $CORELIST $CPULIST +echo ${EARG} "CPU : " ${EOL} ; size_files $CPULIST +echo ${EARG} "OVERALL : " ${EOL} ; size_files $CPULIST $CORELIST $MANLIST \ + $MPLIST +echo ${EARG} "MINIMUM : " ${EOL} ; size_files $CPULIST $CORELIST \ + $OPTMANLIST $REQMANLIST +echo + +for file in $MANLIST +do + base=`basename ${file}` + echo ${EARG} ""${base} : " ${EOL} " ; size_files ${file} +done + +echo ${EARG} "MP : " ${EOL} ; size_files $MPLIST + +echo +for file in $OPTMANLIST +do + base=`basename ${file}` + echo ${EARG} "${base} : " ${EOL} ; size_files ${file} +done + +echo +exit 0 diff --git a/tools/cpu/nios2/.cvsignore b/tools/cpu/nios2/.cvsignore new file mode 100644 index 0000000000..bfdfd995be --- /dev/null +++ b/tools/cpu/nios2/.cvsignore @@ -0,0 +1,14 @@ +aclocal.m4 +autom4te*.cache +config.cache +config.guess +config.log +config.status +config.sub +configure +depcomp +install-sh +Makefile +Makefile.in +missing +mkinstalldirs diff --git a/tools/cpu/nios2/ChangeLog b/tools/cpu/nios2/ChangeLog new file mode 100644 index 0000000000..d8212c0171 --- /dev/null +++ b/tools/cpu/nios2/ChangeLog @@ -0,0 +1,34 @@ +2011-02-02 Ralf Corsépius + + * configure.ac: Require autoconf-2.68, automake-1.11.1. + +2006-12-02 Ralf Corsépius + + * configure.ac: New BUG-REPORT address. + +2006-10-17 Ralf Corsépius + + * configure.ac: Require autoconf-2.60. Require automake-1.10. + +2006-08-15 Kolja Waschk + + * linkcmds.c, linkcmds.h, memory.c, memory.h, sample.ptf: New files. + * bridges.c: corrected detection of bridged connections + * clocks.c: removed a printf + * linkcmds.[ch] new files, added output of linker script + * Makefile.am: added new files + * memory.[ch]: new files, detection of memory in SOPC configuration + * nios2gen.c: updated command line parsing and output control + * output.[ch]: improved output of BSP header file + * ptf.[ch]: added ptf_dump_ptf_item and small fixes + * sample.ptf: new file, sample configuration for nios2gen + * README: updated + +2006-08-10 Joel Sherrill + + * nios2gen.c: Added some very basic support for --help and --version + options along with output that is roughly in GNU format. This is + required by help2man. help2man expects this all to be written to + stdout instead of stderr so this was changed as well. + * ChangeLog: New file. + diff --git a/tools/cpu/nios2/Makefile.am b/tools/cpu/nios2/Makefile.am new file mode 100644 index 0000000000..254d245d27 --- /dev/null +++ b/tools/cpu/nios2/Makefile.am @@ -0,0 +1,25 @@ +## +## $Id$ +## + +ACLOCAL_AMFLAGS = -I ../../../aclocal + +noinst_PROGRAMS = nios2gen + +nios2gen_SOURCES = nios2gen.c \ + bridges.c bridges.h \ + devices.c devices.h \ + clocks.c clocks.h \ + output.c output.h \ + linkcmds.c linkcmds.h \ + memory.c memory.h \ + ptf.h ptf.c + +if HELP2MAN +man_MANS = nios2gen.1 + +nios2gen.1: nios2gen$(EXEEXT) + $(HELP2MAN) -N ./nios2gen >$@ +endif + +include $(top_srcdir)/../../../automake/host.am diff --git a/tools/cpu/nios2/README b/tools/cpu/nios2/README new file mode 100644 index 0000000000..f961dff6b1 --- /dev/null +++ b/tools/cpu/nios2/README @@ -0,0 +1,148 @@ +$Id$ + +nios2gen: + Tool to generate BSP data for boards utilizing NIOS2 soft core processor. + +================================= +What it does + +It creates a sopc.h and linkcmds file for RTEMS nios2 BSPs from one or more inputs: + +1. SOPC System Description PTF + +As an output from SOPC Builder you get a file with extension ".ptf" that fully +describes the SOPC, including all CPUs, memory and integrated peripherals. +(PTF simply means "plain-text file"). + +2. BSP Configuration PTF + +This file, using the same format as the SOPC System Description PTF, describes +which components of the SOPC shall be used by the BSP. For example, there may +be several timers, but a BSP wants at least one named "CLOCK" and optionally +another named "TIMER". This mapping can be specified in the BSP. + +================================= +Contents of the configuration PTF + +There can be definitions of ... + +HEADER: This is written to sopc.h before anything else. Example: + + HEADER = " + #ifndef __SOPC_H + #define __SOPC_H 1 + "; + +EPILOG: This is written to sopc.h after anything else. Example: + + EPILOG = " + #endif + "; + +CLOCKS section: Used to specify names for clocks to be used in definitions in +the sopc.h. The default name (if none is specified here) is the uppercased name +as in the system description PTF. Specify the name you want on the left, the +name in the sopc PTF on the right! Example: + + CLOCKS + { + GLOBAL_CLOCK = "sys_clk"; + } + +MODULES section: Same as clocks but for modules / peripherals. As a special definition, +if the PTF contains more than one nios2 CPU, it /must/ define a CPU to use. Example to +select cpu_0 and rename timer_0 to CLOCK and timer_1 to TIMER: + + MODULES + { + CPU = "cpu_0"; + CLOCK = "timer_0"; + TIMER = "timer_1"; + } + +CLASS xyz sections: These specify what you want in the sopc.h, and how the definitions +shall be named. Actually, the CLASS xyz should look exactly like the corresponding MODULE +specification in the system description PTF of modules belonging to that class; e.g. a +a JTAG UART is originally described like this: + + MODULE jtag_uart_0 + { + class = "altera_avalon_jtag_uart"; + class_version = "1.0"; + iss_model_name = "altera_avalon_jtag_uart"; + SLAVE avalon_jtag_slave + { + SYSTEM_BUILDER_INFO + { + Bus_Type = "avalon"; + Is_Printable_Device = "1"; + Address_Alignment = "native"; + Address_Width = "1"; + Data_Width = "32"; + Has_IRQ = "1"; + Read_Wait_States = "peripheral_controlled"; + Write_Wait_States = "peripheral_controlled"; + JTAG_Hub_Base_Id = "0x04006E"; + JTAG_Hub_Instance_Id = "0"; + MASTERED_BY cpu_0/data_master + { + priority = "1"; + } + IRQ_MASTER cpu_0/data_master + { + IRQ_Number = "2"; + } + Base_Address = "0x08000000"; + } + } + ... + } + +If you want to have definitions about its base address and irq number in your sopc.h, +define a CLASS for altera_avalon_jtag_uart that matches the MODULE description above, +but instead of values for the items you specify names to be used in your sopc.h (You +can omit items from the MODULE as you like, but the section nesting must match; and +section names (such as avalon_jtag_slave for the SLAVE section) also have to match) + + CLASS altera_avalon_jtag_uart + { + SLAVE avalon_jtag_slave + { + SYSTEM_BUILDER_INFO + { + Base_Address = "BASE_ADDR"; + IRQ_MASTER { IRQ_Number = "IRQ"; } + } + } + } + +The output for jtag_uart_0 will be: + + #define JTAG_UART_BASE_ADDR 0x021208D0 + #define JTAG_UART_IRQ 1 + +There are some values with special meaning to nios2gen, + +N2G_CLOCKREF_CLOCK: This should be used whereever the value in the SOPC PTF +specifies the name of a clock. nios2gen will use whatever you configured for +the selected clock in your CLOCKS section. + +N2G_CLOCKREF_DEVICE: This should be used whereever the value in the SOPC PTF +specifies the name of a module. nios2gen will use whatever you configured for +the selected module in your MODULES section. + +Additionally, you can specify items in your CLASSes so that nios2gen will include +constant definitions in the sopc.h whenever such CLASS is present. The format is + + N2G_DEFINE_xyz = "123" + +and will result in + +#define MODULENAME_xyz 123 + + + + + + + diff --git a/tools/cpu/nios2/bridges.c b/tools/cpu/nios2/bridges.c new file mode 100644 index 0000000000..be5e889b5e --- /dev/null +++ b/tools/cpu/nios2/bridges.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +/********************************************************/ +/* Find bus bridges */ + +/* This part of the program builds a list with pairs of bus + master port names (each is "device name/master port name"). + It is then possible to find if a given master is actually + available under a different master port name through bridges. + */ + +/* Typical example with external SRAM that is slave of + tristate_bridge_0/tristate_master, and + tristate_bridge_0 itself is slave of cpu0/data_master, the + bridge information would be stored as this bus_bridge_pair: + mastered_by = "cpu0/data_master" and + bridges_to = "tristate_bridge_0/tristate_master". + That allows to deduce that SRAM is actually mastered by + cpu0/data_master. If there were any address or bus width + translations, it should be noted in the bridges list... For + now we simply assume that bridges never translate anything. + */ + +#include +#include + +#include "ptf.h" +#include "bridges.h" + +int is_bridged( + char *cpu_master, + char *dev_master, + bus_bridge_pair *bridges) +{ + char *curr_master; + bus_bridge_pair *bbp; + + if(strcmp(cpu_master, dev_master) == 0) return 1; /* cpu directly masters dev */ + + for(bbp = bridges; bbp != NULL; bbp=bbp->next) + { + if(strcmp(cpu_master, bbp->mastered_by) == 0 && + is_bridged(bbp->bridges_to, dev_master, bridges)) + { + return 1; /* cpu masters dev via bridge */ + } + }; + + return 0; +} + +void add_bridge_master(struct ptf_item *pi, void *arg) +{ + struct { char *bt; bus_bridge_pair **bridges; } *binfo = arg; + bus_bridge_pair *new_pair; + + if(binfo->bridges == 0) return; + + new_pair = (bus_bridge_pair *)malloc(sizeof(bus_bridge_pair)); + if(new_pair == NULL) return; + + new_pair->bridges_to = binfo->bt; + new_pair->mastered_by = pi->item[pi->level]->value; + new_pair->next = *(binfo->bridges); + *(binfo->bridges) = new_pair; +} + +void add_bridge_dest(struct ptf_item *pi, void *arg) +{ + struct ptf maby_section = { section, "MASTERED_BY", 0, 0, 0 }; + struct ptf_item maby = { 1, &maby_section }; + + char *bridge_name = pi->item[1]->value; + char *bridge_dest = pi->item[pi->level]->value; + struct { char *bt; bus_bridge_pair **bridges; } binfo; + + binfo.bridges = arg; + binfo.bt = (char*)malloc(strlen(bridge_name)+strlen(bridge_dest) + 2); + strcpy(binfo.bt, bridge_name); + strcat(binfo.bt, "/"); + strcat(binfo.bt, bridge_dest); + + ptf_match(pi->item[pi->level-1]->sub, &maby, add_bridge_master, &binfo); + + /* binfo.bt is NOT freed here */ +} + +bus_bridge_pair *find_bridges(struct ptf *p) +{ + bus_bridge_pair *bridges = 0; + + struct ptf system = { section, "SYSTEM", 0, 0, 0 }; + struct ptf module = { section, "MODULE", 0, 0, 0 }; + struct ptf slave = { section, "SLAVE", 0, 0, 0 }; + struct ptf syb = { section, "SYSTEM_BUILDER_INFO", 0, 0, 0 }; + struct ptf to = { item, "Bridges_To", 0, 0, 0 }; + struct ptf_item brdg = { 5, &system, &module, &slave, &syb, &to }; + + ptf_match(p, &brdg, add_bridge_dest, &bridges); + + return bridges; +} + + + + diff --git a/tools/cpu/nios2/bridges.h b/tools/cpu/nios2/bridges.h new file mode 100644 index 0000000000..02d983871d --- /dev/null +++ b/tools/cpu/nios2/bridges.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef __NIOS2GEN_BRIDGES_H +#define __NIOS2GEN_BRIDGES_H 1 + +typedef struct bus_bridge_pair +{ + char *mastered_by; + char *bridges_to; + struct bus_bridge_pair *next; +} +bus_bridge_pair; + +bus_bridge_pair *find_bridges(struct ptf *p); + +int is_bridged( + char *cpu_master, + char *dev_master, + bus_bridge_pair *bridges); + +#endif + + diff --git a/tools/cpu/nios2/clocks.c b/tools/cpu/nios2/clocks.c new file mode 100644 index 0000000000..5a3293ef29 --- /dev/null +++ b/tools/cpu/nios2/clocks.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include "ptf.h" +#include "clocks.h" + +#include + +void add_clock_spec(struct ptf_item *pi, void *arg) +{ + clock_desc **clocks = arg; + clock_desc *new_clock; + unsigned long freq; + + new_clock = (clock_desc*)malloc(sizeof(clock_desc)); + if(new_clock == NULL) return; + + new_clock->freq = strtoul(pi->item[pi->level]->value, 0, 0); + + new_clock->cfgname = NULL; + new_clock->name = pi->item[pi->level-1]->value; + new_clock->next = *clocks; + + + *clocks = new_clock; +} + +void set_clock_cfgname(struct ptf_item *pi, void *arg) +{ + clock_desc *clock = arg; + clock->cfgname = pi->item[pi->level]->name; +} + +clock_desc *find_clocks( struct ptf *sopc, struct ptf *cfg ) +{ + clock_desc *clocks, *reverse; + + struct ptf system = { section, "SYSTEM", 0, 0, 0 }; + struct ptf wizargs = { section, "WIZARD_SCRIPT_ARGUMENTS", 0, 0, 0 }; + struct ptf all = { section, "CLOCKS", 0, 0, 0 }; + struct ptf clock = { section, "CLOCK", 0, 0, 0 }; + struct ptf freq = { item, "frequency", 0, 0, 0 }; + struct ptf_item clk_spec = { 5, &system, &wizargs, &all, &clock, &freq }; + + struct ptf named = { item, 0, 0, 0, 0 }; + struct ptf_item clk_cfg = { 2, &all, &named }; + + clocks = NULL; + ptf_match(sopc, &clk_spec, add_clock_spec, &clocks); + + /* Reverse the linked list and look for configured names */ + + reverse = NULL; + while(clocks) + { + clock_desc *tmp = clocks; + clocks = clocks->next; + tmp->next = reverse; + reverse = tmp; + + named.value = tmp->name; + ptf_match(cfg, &clk_cfg, set_clock_cfgname, tmp); + if(tmp->cfgname == NULL) tmp->cfgname = ptf_defused_name(tmp->name); + }; + + return reverse; +} + + + diff --git a/tools/cpu/nios2/clocks.h b/tools/cpu/nios2/clocks.h new file mode 100644 index 0000000000..ef8395d39c --- /dev/null +++ b/tools/cpu/nios2/clocks.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef __NIOS2GEN_CLOCKS_H +#define __NIOS2GEN_CLOCKS_H 1 + +#include "ptf.h" + +typedef struct clockdsc +{ + char *name; + char *cfgname; + unsigned long freq; + struct clockdsc *next; +} +clock_desc; + +clock_desc *find_clocks( struct ptf *ptf, struct ptf *cfg ); + +#endif + diff --git a/tools/cpu/nios2/configure.ac b/tools/cpu/nios2/configure.ac new file mode 100644 index 0000000000..a2b2041074 --- /dev/null +++ b/tools/cpu/nios2/configure.ac @@ -0,0 +1,23 @@ +## Process this file with autoconf to produce a configure script. +## +## $Id$ + +AC_PREREQ([2.68]) +AC_INIT([rtems-tools-cpu-nios2],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([nios2gen.c]) +RTEMS_TOP(../../..) + +RTEMS_CANONICAL_TARGET_CPU + +AM_INIT_AUTOMAKE([foreign 1.11.1]) +AM_MAINTAINER_MODE + +AC_PROG_CC +AC_CHECK_PROGS(HELP2MAN,help2man) +AM_CONDITIONAL(HELP2MAN,test -n "$HELP2MAN" ) + +RTEMS_TOOLPATHS + +# Explicitly list all Makefiles here +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/tools/cpu/nios2/devices.c b/tools/cpu/nios2/devices.c new file mode 100644 index 0000000000..054d1cc29f --- /dev/null +++ b/tools/cpu/nios2/devices.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include +#include + +#include "ptf.h" +#include "bridges.h" +#include "devices.h" + +void add_device(device_desc **dl, struct ptf *dev) +{ + device_desc *eds; + + for(eds = *dl; eds; eds = eds->next) + { + if(eds->ptf == dev) + { + eds->slaves++; + return; + }; + }; + + eds = (device_desc *)malloc(sizeof(device_desc)); + eds->slaves = 1; + eds->ptf = dev; + eds->next = *dl; + *dl = eds; +} + +void check_and_add_device(struct ptf_item *pi, void *arg) +{ + struct ptf *module = pi->item[pi->level-3]; + struct ptf *sysinfo = pi->item[pi->level-2]; + char *master_name = pi->item[pi->level]->value; + + struct { char *dm; char *im; device_desc **dl; bus_bridge_pair *bridges; } *dinfo = arg; + + if(is_bridged(dinfo->dm, master_name, dinfo->bridges) || + is_bridged(dinfo->im, master_name, dinfo->bridges)) + { + struct ptf *ni = ptf_alloc_item(item, "N2G_Selected", "1"); + if(ni != NULL) + { + ni->next = sysinfo->sub; + sysinfo->sub = ni; + }; + add_device(dinfo->dl, module); + }; +} + +void set_dev_cfgname(struct ptf_item *pi, void *arg) +{ + device_desc *dev = arg; + dev->cfgname = pi->item[pi->level]->name; +} + + +device_desc *find_devices( + struct ptf *ptf, + struct ptf *cfg, + struct ptf *cpu, + bus_bridge_pair *bridges) +{ + struct ptf system = { section, "SYSTEM", 0, 0, 0 }; + struct ptf module = { section, "MODULE", 0, 0, 0 }; + struct ptf slave = { section, "SLAVE", 0, 0, 0 }; + struct ptf syb = { section, "SYSTEM_BUILDER_INFO", 0, 0, 0 }; + struct ptf maby = { section, "MASTERED_BY", 0, 0, 0 }; + struct ptf_item brdg = { 5, &system, &module, &slave, &syb, &maby }; + + struct ptf modules = { section, "MODULES", 0, 0, 0 }; + struct ptf named = { item, 0, 0, 0, 0}; + struct ptf_item devcf = { 2, &modules, &named }; + + struct { char *dm; char *im; device_desc **dl; bus_bridge_pair *bridges; } dinfo; + + device_desc *found, *reverse; + + found = NULL; + + add_device(&found, cpu); /* The CPU is "self-connected", add it */ + + dinfo.dl = &found; + dinfo.bridges = bridges; + dinfo.dm = (char *)malloc(strlen(cpu->value)+13); + dinfo.im = (char *)malloc(strlen(cpu->value)+20); + + strcpy(dinfo.im, cpu->value); + strcat(dinfo.im, "/"); + strcpy(dinfo.dm, dinfo.im); + strcat(dinfo.dm, "data_master"); + strcat(dinfo.im, "instruction_master"); + + /* "Available" is any MODULE with a SLAVE section that is MASTERED_BY + either instr_master or data_master of selected CPU, either directly + or through a bridge. See code above for more info about bridges. + */ + + ptf_match(ptf, &brdg, check_and_add_device, &dinfo); + + free(dinfo.dm); + free(dinfo.im); + + /* Reverse the linked list */ + + reverse = NULL; + while(found) + { + device_desc *tmp = found; + found = found->next; + + tmp->next = reverse; + reverse = tmp; + + named.value = tmp->ptf->value; + tmp->cfgname = NULL; + ptf_match(cfg, &devcf, set_dev_cfgname, tmp); + if(tmp->cfgname == NULL) tmp->cfgname = ptf_defused_name(tmp->ptf->value); + }; + + return reverse; +} + diff --git a/tools/cpu/nios2/devices.h b/tools/cpu/nios2/devices.h new file mode 100644 index 0000000000..5e62ea2c00 --- /dev/null +++ b/tools/cpu/nios2/devices.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef __NIOS2GEN_DEVICES_H +#define __NIOS2GEN_DEVICES_H 1 + +#include "ptf.h" +#include "bridges.h" + +typedef struct dev_descr +{ + int slaves; + char *cfgname; + struct ptf *ptf; + struct dev_descr *next; +} +device_desc; + +device_desc *find_devices( + struct ptf *ptf, + struct ptf *cfg, + struct ptf *cpu, + bus_bridge_pair *bridges); + +#endif diff --git a/tools/cpu/nios2/linkcmds.c b/tools/cpu/nios2/linkcmds.c new file mode 100644 index 0000000000..28a71cbbc0 --- /dev/null +++ b/tools/cpu/nios2/linkcmds.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include +#include + +#include "ptf.h" +#include "devices.h" +#include "output.h" /* is_not_connected, fwrite_value, etc */ +#include "memory.h" +#include "linkcmds.h" + +typedef struct +{ + FILE *file; + struct ptf *cfg, *cpu; + device_desc *devices; + memory_desc *memory; +} +lcmd_desc; + +void fwrite_lcmds_section(struct ptf_item *pi, void *arg) +{ + lcmd_desc *li = (lcmd_desc *)arg; + struct ptf *p; + struct ptf_item lpi; + char *location = NULL; + char *section_name = pi->item[1]->value; + + if(section_name == 0) + { + fprintf(stderr, "Found a LINKER/SECTION without name, ignoring it.\n"); + return; + }; + + p = ptf_find(pi->item[1]->sub, &lpi, item, "LOCATION", 0); + if(p) + { + location = p->value; + } + else + { + if(strcmp(section_name, "entry") == 0) + { + p = ptf_find(li->cpu, &lpi, item, "reset_slave", 0); + } + else if(strcmp(section_name, "exceptions") == 0) + { + p = ptf_find(li->cpu, &lpi, item, "exc_slave", 0); + }; + if(p) location = p->value; + /* TODO: This doesn't work yet, parse full slave address, translate into our naming */ + } + + if(location == 0) + { + fprintf(stderr, "No LOCATION configured for section '%s'!\n", pi->item[1]->value); + return; + }; + + fprintf(li->file, " .%s :\n {\n", pi->item[1]->value); + fprintf(li->file, pi->item[2]->value); + fprintf(li->file, " } > %s\n\n", location); +} + +void fwrite_linkcmds_file(FILE *file, struct ptf *cfg, struct ptf *cpu, device_desc *devices, memory_desc *memory) +{ + struct ptf *p; + struct ptf_item pi; + memory_desc *tmd; + lcmd_desc linfo; + + struct ptf ptlink = { section, "LINKCMDS", 0, 0, 0 }; + struct ptf ptleadtext = { item, "LEADTEXT", 0, 0, 0 }; + struct ptf ptepilog = { item, "EPILOG", 0, 0, 0 }; + struct ptf_item malihead = { 2, &ptlink, &ptleadtext }; + struct ptf_item maliepil = { 2, &ptlink, &ptepilog }; + + struct ptf ptsect = { section, "SECTION", 0, 0, 0 }; + struct ptf ptcmds = { item, "COMMANDS", 0, 0, 0 }; + struct ptf ptstabs = { item, "STABS", 0, 0, 0 }; + struct ptf_item malisect = { 3, &ptlink, &ptsect, &ptcmds }; + struct ptf_item malistabs = { 2, &ptlink, &ptstabs }; + + linfo.cfg = cfg; + linfo.cpu = cpu; + linfo.file = file; + linfo.devices = devices; + linfo.memory = memory; + + ptf_match(cfg, &malihead, fwrite_value, file); + + fprintf(file, "MEMORY\n{\n"); + for(tmd = linfo.memory; tmd; tmd = tmd->next) + { + fprintf(file, " %s : ORIGIN = 0x%08X, LENGTH = 0x%08X\n", tmd->dev->cfgname, tmd->base, tmd->size); + } + fprintf(file, "}\n\nSECTIONS\n{\n"); + + ptf_match(cfg, &malisect, fwrite_lcmds_section, &linfo); + ptf_match(cfg, &malistabs, fwrite_value, file); + + for(tmd = linfo.memory; tmd; tmd = tmd->next) + { + fprintf(file, " %s : ORIGIN = 0x%08X, LENGTH = 0x%08X\n", tmd->dev->cfgname, tmd->base, tmd->size); + } + + + fprintf(file, "}\n\n"); + + ptf_match(cfg, &maliepil, fwrite_value, file); +} + + diff --git a/tools/cpu/nios2/linkcmds.h b/tools/cpu/nios2/linkcmds.h new file mode 100644 index 0000000000..d2686d5e8e --- /dev/null +++ b/tools/cpu/nios2/linkcmds.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef __LINKCMDS_H +#define __LINKCMDS_H 1 + +#include +#include +#include + +#include "ptf.h" +#include "devices.h" + +void fwrite_linkcmds_file(FILE *file, struct ptf *cfg, struct ptf *cpu, device_desc *devices, memory_desc *memory); + +#endif + + diff --git a/tools/cpu/nios2/memory.c b/tools/cpu/nios2/memory.c new file mode 100644 index 0000000000..c697e15430 --- /dev/null +++ b/tools/cpu/nios2/memory.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include +#include + +#include "ptf.h" +#include "devices.h" +#include "memory.h" + +memory_desc *find_memory(device_desc *devices) +{ + struct ptf *p; + struct ptf_item pi; + memory_desc *tmd, *memory; + + /********************************************************/ + /* Check which of the devices are memory, sort by size */ + + if(devices) + { + struct ptf *p, *s; + struct ptf_item pi; + device_desc *dd; + + memory = NULL; + + for(dd = devices; dd; dd=dd->next) + { + p = ptf_find(dd->ptf->sub, &pi, item, "Is_Memory_Device", "1"); + if(p != NULL && pi.level>0) + { + s = pi.item[pi.level-1]; + p = ptf_find(s, &pi, item, "Base_Address", 0); + }; + + if(p != NULL) + { + tmd = (memory_desc*)malloc(sizeof(memory_desc)); + + if(tmd != NULL) + { + tmd->base = strtoul(p->value, 0, 0); + + p = ptf_find(s, &pi, item, "Address_Span", 0); + if(p != 0) + { + tmd->size = strtoul(p->value, 0, 0); + } + else + { + tmd->size = 0; + p = ptf_find(s, &pi, item, "Address_Width", 0); + if(p) tmd->size = 1 << strtoul(p->value, 0, 0); + p = ptf_find(s, &pi, item, "Data_Width", 0); + if(p) tmd->size *= (strtoul(p->value, 0, 0) >> 3); + }; + + if(tmd->size == 0) + { + free(tmd); + } + else + { + tmd->dev = dd; + + if(memory == NULL) + { + tmd->next = NULL; + memory = tmd; + } + else + { + if(tmd->size > memory->size) + { + tmd->next = memory; + memory = tmd; + } + else + { + memory_desc *uplink = memory; + while(uplink->next != NULL && uplink->next->size > tmd->size) uplink=uplink->next; + tmd->next = uplink->next; + uplink->next = tmd; + }; + }; + }; + }; + }; + }; + }; + + return memory; +} + + diff --git a/tools/cpu/nios2/memory.h b/tools/cpu/nios2/memory.h new file mode 100644 index 0000000000..0fe364c4b9 --- /dev/null +++ b/tools/cpu/nios2/memory.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef __MEMORY_H +#define __MEMORY_H 1 + +#include "devices.h" + +typedef struct memdsc +{ + unsigned long base; + unsigned long size; + device_desc *dev; + struct memdsc *next; +} +memory_desc; + +memory_desc *find_memory(device_desc *devices); + +#endif + + diff --git a/tools/cpu/nios2/nios2gen.c b/tools/cpu/nios2/nios2gen.c new file mode 100644 index 0000000000..9c36a48a99 --- /dev/null +++ b/tools/cpu/nios2/nios2gen.c @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include +#include + +#include "ptf.h" +#include "bridges.h" +#include "clocks.h" +#include "devices.h" +#include "memory.h" +#include "output.h" +#include "linkcmds.h" + +#define NIOS2GEN_PACKAGE PACKAGE +#define NIOS2GEN_VERSION VERSION + +#include "getopt.h" + +/********************************************************/ + +void store_ptf_parent(struct ptf_item *pi, void *arg) +{ + struct ptf *p = pi->item[pi->level-1]; + *(struct ptf **)arg = p; +} + +/********************************************************/ + +void store_ptf_ptr(struct ptf_item *pi, void *arg) +{ + struct ptf *p = pi->item[pi->level]; + *(struct ptf **)arg = p; +} + +/********************************************************/ + +void printf_ptf_value(struct ptf_item *pi, void *arg) +{ + struct ptf *p = pi->item[pi->level]; + printf(*(char **)arg, p->value); +} + +/********************************************************/ + +void read_include_file(struct ptf_item *pi, void *arg) +{ + struct ptf *inc, *next; + struct ptf *p = pi->item[pi->level]; + + inc = ptf_parse_file(p->value); + + if(inc == NULL) + { + fprintf(stderr, "Warning: couldn't parse included '%s'.\n", p->value); + return; + }; + + printf("Successfully read included PTF file %s.\n", p->value); + + next = p->next; + for(p->next = inc; p->next != NULL; p = p->next); + p->next = next; +} + +/********************************************************/ + +void version(FILE *f) +{ +fprintf(f, + "nios2gen (" __DATE__ ")\n" + " Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de\n" + "\n" + " The license and distribution terms for this file may be\n" + " found in the file LICENSE in this distribution or at\n" + " http://www.rtems.com/license/LICENSE.\n" + , VERSION +); +} + +void usage (FILE *f, char *errmsg) +{ + char *info = "Purpose:\n Create RTEMS nios2 BSP configuration from Altera SOPC description\n"; + if(errmsg) info=errmsg; + version(f); + fprintf(f,"\n%s\nUsage: nios2gen [OPTIONS] [CONFIG PTF] [CONFIG PTF]...\n", info); + fprintf(f," -h --help Print help and exit\n"); + fprintf(f," -V --version Print version and exit\n"); + fprintf(f," -bFILENAME --bspheader=FILENAME Output BSP configuration header file (default='sopc.h')\n"); + fprintf(f," -B --no-bspheader Do not output BSP configuration header file\n"); + fprintf(f," -lFILENAME --linkcmds=FILENAME Output linker script (default='linkcmds')\n"); + fprintf(f," -L --no-linkcmds Do not output linker script\n"); + fprintf(f," -pFILENAME --parsed=FILENAME Output PTF contents as long list (default: don't)\n"); + fprintf(f," -P --no-parsed Do not output PTF contents as long list\n"); + fprintf(f," -q --quiet Do not print progress info to stdout\n\n"); + fprintf(f,"Using \"-\" as the FILENAME means standard output (stdout).\n"); +} + +/********************************************************/ + +int main(int argc, char *argv[]) +{ + struct ptf *sopc, *cfg, *p, *cpu; + struct ptf_item pi; + device_desc *devices; + bus_bridge_pair *bridges; + clock_desc *clocks; + memory_desc *memory; + + int verbose = 1; + int output_order = 127; + char *parsed_filename = NULL; + int output_parsed = 0; + char *bspheader_filename = "sopc.h"; + int output_bspheader = 1; + char *linkcmds_filename = "linkcmds"; + int output_linkcmds = 2; + + optarg = 0; + optind = 1; + opterr = 1; + optopt = '?'; + + if(argc > 126) + { + usage(stderr,"Too many commandline arguments!\n"); + return -1; + }; + + while(1) + { + int c, long_index = 0; + static char *optstring = "hVBb:Ll:Pp:q"; + + static struct option long_options[] = + { + { "help", 0, NULL, 'h' }, + { "version", 0, NULL, 'V' }, + { "no-bspheader", 0, NULL, 'B' }, + { "bspheader", 1, NULL, 'b' }, + { "no-linkcmds", 0, NULL, 'L' }, + { "linkcmds", 1, NULL, 'l' }, + { "no-parsed", 0, NULL, 'P' }, + { "parsed", 1, NULL, 'p' }, + { "quiet", 0, NULL, 'q' }, + { NULL, 0, NULL, 0 } + }; + + c = getopt_long (argc, argv, optstring, long_options, &long_index); + + if(c == -1) break; /* Exit from while(1) loop */ + + switch(c) + { + case 'q': /* Be quiet */ + verbose = 0; + break; + + case 'h': /* Print help and exit */ + usage(stdout,NULL); + return 0; + + case 'V': /* Print version and exit */ + version(stdout); + return 0; + + case 'B': /* Do not output BSP configuration header file */ + output_bspheader = 0; + break; + + case 'b': /* Output BSP configuration header file */ + bspheader_filename = optarg; + output_bspheader = output_order; + output_order--; + break; + + case 'L': /* Do not output linker script */ + output_linkcmds = 0; + break; + + case 'l': /* Output linker script */ + linkcmds_filename = optarg; + output_linkcmds = output_order; + output_order--; + break; + + case 'P': /* Do not output PTF contents */ + output_parsed = 0; + break; + + case 'p': /* Output PTF contents as long list */ + parsed_filename = optarg; + output_parsed = output_order; + output_order--; + break; + + case 0: + case '?': + return -1; + + default: + fprintf(stderr, "%s: unknown option: %c\n", NIOS2GEN_PACKAGE, c); + }; + }; + + if(optind >= argc) + { + usage(stderr,"No PTF specified!\n"); + return -1; + }; + + /********************************************************/ + + sopc = ptf_parse_file(argv[optind]); + if(sopc == NULL) + { + fprintf(stderr, "Could not parse system description PTF '%s'.\n", argv[optind]); + return -1; + }; + + if(verbose) printf("Successfully read SOPC PTF file %s.\n", argv[optind]); + + /********************************************************/ + + cfg = NULL; + + for(optind++;optindvalue) class_spec.item[1]->value = cpu->value; + + cpu_count = ptf_match(sopc, &class_spec, store_ptf_parent, &cpu); + + if(cpu_count > 1) + { + fprintf(stderr, "There is more than one CPU. Please specify the one\n"); + fprintf(stderr, "you want to use with this BSP in your config file.\n"); + fprintf(stderr, "The available CPUs are named as follows:\n"); + ptf_match(sopc, &class_spec, printf_ptf_value, " %s\n"); + return -1; + }; + + if(cpu_count == 0) + { + fprintf(stderr, "There is no NIOS2 cpu in the system.\n"); + return -1; + } + }; + + if(verbose) + { + printf("Using NIOS II CPU '%s'.\n", cpu->value); + printf("Only modules mastered by this CPU are considered now.\n"); + }; + + /********************************************************/ + /* Find Bridges */ + + if(verbose) printf("Looking for bus bridges...\n"); + + bridges = find_bridges(sopc); + + if(verbose) + { + if(bridges) + { + bus_bridge_pair *bbp; + for(bbp = bridges; bbp; bbp=bbp->next) + { + printf("Found bridge: %s\n", bbp->mastered_by); + printf(" \\_%s\n", bbp->bridges_to); + }; + } + else + { + printf("No bridges present.\n"); + }; + }; + + /********************************************************/ + /* Find clocks */ + + if(verbose) printf("Looking for clock definitions...\n"); + + clocks = find_clocks(sopc, cfg); + + if(verbose) + { + if(clocks) + { + clock_desc *cs; + for(cs = clocks; cs; cs = cs->next) + { + printf("Found clock \"%s\" (%lu Hz), naming it %s\n", cs->name, cs->freq, cs->cfgname); + }; + } + else + { + printf("No clocks present.\n"); + }; + }; + + /********************************************************/ + /* Find other devices available to the selected CPU */ + + if(verbose) printf("Looking for devices...\n"); + + devices = find_devices(sopc, cfg, cpu, bridges); + + if(verbose) + { + if(devices) + { + device_desc *dd; + for(dd = devices; dd; dd=dd->next) + { + printf("Found device \"%s\", naming it %s\n", dd->ptf->value, dd->cfgname); + }; + } + else + { + printf("No devices present.\n"); + }; + }; + + /********************************************************/ + /* Find out which devices are actually memory */ + + if(verbose) printf("Looking for memory...\n"); + + memory = find_memory(devices); + + if(verbose) + { + if(memory) + { + memory_desc *md; + for(md = memory; md; md=md->next) + { + printf("Found memory in \"%s\", base=0x%08X, size=%lu bytes\n", + md->dev->cfgname, + md->base, md->size); + }; + } + else + { + printf("None of the devices seems to provide memory?!\n"); + }; + }; + + + /********************************************************/ + /* Output files in the order they were specified + on the command line */ + + { + int i; + for(i=0;i<3;i++) + { + if(output_bspheader>0 + && output_bspheader>=output_linkcmds + && output_bspheader>=output_parsed) + { + output_bspheader = 0; + if(bspheader_filename == NULL || (bspheader_filename[0]=='-' && bspheader_filename[1]==0)) + { + fwrite_header_file(stdout, cfg, devices, clocks); + } + else + { + FILE *f = fopen(bspheader_filename, "w"); + if(!f) + { + perror(bspheader_filename); + return -1; + } + else + { + fwrite_header_file(f, cfg, devices, clocks); + fclose(f); + } + } + }; + if(output_linkcmds>0 + && output_linkcmds>=output_bspheader + && output_linkcmds>=output_parsed) + { + output_linkcmds = 0; + if(linkcmds_filename == NULL || (linkcmds_filename[0]=='-' && linkcmds_filename[1]==0)) + { + fwrite_linkcmds_file(stdout, cfg, cpu, devices, memory); + } + else + { + FILE *f = fopen(linkcmds_filename, "w"); + if(!f) + { + perror(linkcmds_filename); + return -1; + } + else + { + fwrite_linkcmds_file(f, cfg, cpu, devices, memory); + fclose(f); + } + } + }; + if(output_parsed>0 + && output_parsed>=output_linkcmds + && output_parsed>=output_bspheader) + { + output_parsed = 0; + if(parsed_filename == NULL || (parsed_filename[0]=='-' && parsed_filename[1]==0)) + { + ptf_printf(stdout, sopc, ""); + } + else + { + FILE *f = fopen(parsed_filename, "w"); + if(!f) + { + perror(parsed_filename); + return -1; + } + else + { + ptf_printf(f, sopc, ""); + fclose(f); + } + } + }; + } + }; + + if(verbose) printf("Done.\n"); + + return 0; +} + +/* vi:ts=4: + */ + + diff --git a/tools/cpu/nios2/output.c b/tools/cpu/nios2/output.c new file mode 100644 index 0000000000..bd4a30b0fe --- /dev/null +++ b/tools/cpu/nios2/output.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include +#include + +#include "ptf.h" +#include "devices.h" +#include "output.h" + +typedef struct +{ + FILE *file; + device_desc *dev; + char *def_name; + char *orig_value; + clock_desc *clocks; + device_desc *devices; +} +out_desc; + +int is_not_connected(struct ptf_item *pi) +{ + if(pi->item[0] == NULL) return 0; + if(pi->item[0]->name == NULL) return 0; + + if(strcmp(pi->item[0]->name, "SLAVE") == 0) + { + struct ptf *t; + struct ptf_item ti; + t = ptf_find(pi->item[0]->sub, &ti, item, "N2G_Selected", "1"); + + if(t == NULL) return 1; + }; + + return 0; +} + +void fwrite_devhead_def(struct ptf_item *pi, void *arg) +{ + out_desc *dinfo = arg; + + if(pi != NULL) if(is_not_connected(pi)) return; + + fprintf(dinfo->file, "#define %s_%s %s\n", + dinfo->dev->cfgname, dinfo->def_name, dinfo->orig_value); +} + +void fwrite_devhead_line(struct ptf_item *pi, void *arg) +{ + out_desc *dinfo = arg; + + if(is_not_connected(pi)) return; + + if(strncmp(dinfo->orig_value, "N2G_", 4)==0) + { + if(strncmp(dinfo->orig_value, "N2G_CLOCKREF_", 13)==0) + { + clock_desc *c; + for(c = dinfo->clocks; c; c=c->next) + { + if(strcmp(c->name, pi->item[pi->level]->value) == 0) + { + fprintf(dinfo->file, "#define %s_%s %s\n", + dinfo->dev->cfgname, dinfo->orig_value + 13, c->cfgname); + break; + }; + }; + } + else if(strncmp(dinfo->orig_value, "N2G_DEVICEREF_", 14)==0) + { + device_desc *d; + for(d = dinfo->devices; d; d=d->next) + { + if(strcmp(d->ptf->value, pi->item[pi->level]->value) == 0) + { + fprintf(dinfo->file, "#define %s_%s %s\n", + dinfo->dev->cfgname, dinfo->orig_value + 14, d->cfgname); + break; + }; + }; + } + } + else + { + fprintf(dinfo->file, "#define %s_%s %s\n", + dinfo->dev->cfgname, dinfo->orig_value, + pi->item[pi->level]->value); + }; +} + +void fwrite_device_header(struct ptf_item *pi, void *arg) +{ + struct ptf *f; + struct ptf_item fi; + out_desc *dinfo = arg; + + /* This is called for every matching CLASS section in the + configuration. The following loop iterates through all + items in the CLASS section regardless of their nesting level */ + + f = ptf_find(pi->item[pi->level]->sub, &fi, item, 0, 0); + + while(f != NULL) + { + dinfo->orig_value = f->value; + if(f->name && strncmp(f->name, "N2G_DEFINE_", 11)==0) + { + dinfo->def_name = f->name + 11; + if(fi.level >= 2) + { + fi.level--; /* match only the enclosing section */ + ptf_match(dinfo->dev->ptf->sub, &fi, fwrite_devhead_def, dinfo); + fi.level++; + } + else + { + fwrite_devhead_def( 0, dinfo ); + }; + } + else + { + f->value = 0; /* Match ANY value */ + ptf_match(dinfo->dev->ptf->sub, &fi, fwrite_devhead_line, dinfo); + f->value = dinfo->orig_value; + }; + f = ptf_next(&fi, item, 0, 0); + }; +} + +void fwrite_value(struct ptf_item *pi, void *arg) +{ + FILE *file = arg; + fputs(pi->item[pi->level]->value, file); +} + +void fwrite_header_file( FILE *file, struct ptf *cfg, device_desc *devices, clock_desc *clocks) +{ + struct ptf *p; + struct ptf_item pi; + + struct ptf aclass = { section, "CLASS", 0, 0, 0 }; + struct ptf_item matchaclass = { 1, &aclass }; + + struct ptf bspsect = { section, "BSPHEADER", 0, 0, 0 }; + struct ptf leadtext = { item, "LEADTEXT", 0, 0, 0 }; + struct ptf_item matchleadtext = { 2, &bspsect, &leadtext }; + + struct ptf epilog = { item, "EPILOG", 0, 0, 0 }; + struct ptf_item matchepilog = { 2, &bspsect, &epilog }; + + out_desc dinfo; + + dinfo.file = file; + dinfo.clocks = clocks; + dinfo.devices = devices; + + ptf_match(cfg, &matchleadtext, fwrite_value, file); + + if(clocks) + { + clock_desc *cs; + for(cs = clocks; cs; cs = cs->next) + { + fprintf(file, "#define %s_FREQ %luu\n", cs->cfgname, cs->freq); + }; + }; + + if(devices) + { + for(dinfo.dev = devices; dinfo.dev; dinfo.dev=dinfo.dev->next) + { + /* fprintf(file, "\n#define SOPC_HAS_%s 1\n", dinfo.dev->cfgname); */ + + p = ptf_find(dinfo.dev->ptf, &pi, item, "class", 0); + if(p) + { + aclass.value = p->value; + ptf_match(cfg, &matchaclass, fwrite_device_header, &dinfo); + }; + }; + }; + + ptf_match(cfg, &matchepilog, fwrite_value, file); +} + + diff --git a/tools/cpu/nios2/output.h b/tools/cpu/nios2/output.h new file mode 100644 index 0000000000..ad36629bf8 --- /dev/null +++ b/tools/cpu/nios2/output.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef __OUTPUT_H +#define __OUTPUT_H 1 + +#include +#include +#include + +#include "ptf.h" +#include "clocks.h" +#include "devices.h" + +void fwrite_value(struct ptf_item *pi, void *arg); +void fwrite_header_file(FILE *file, struct ptf *cfg, device_desc *devices, clock_desc *clocks); + +#endif + + diff --git a/tools/cpu/nios2/ptf.c b/tools/cpu/nios2/ptf.c new file mode 100644 index 0000000000..db62e557b7 --- /dev/null +++ b/tools/cpu/nios2/ptf.c @@ -0,0 +1,853 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include +#include +#include "ptf.h" + +#define PTFPARSER_MAXDEPTH 20 +#define PTFPARSER_NAMEBUFSIZE 1024 +#define PTFPARSER_VALUEBUFSIZE 4096 + +#define DEBUG_EXPECTATIONS 1 +#define DEBUG_READVALUES 2 +#define DEBUG_FINDER 4 +#define DEBUG 0 + +struct ptf_parser_state +{ + struct ptf *tree; + struct ptf *current_in[PTFPARSER_MAXDEPTH]; + struct ptf *current_item; + + long line; /* starts with 1, increments whenever a LF (ASCII 10) passes */ + int section_level; /* starts at 0, incremented at {, decremented at } */ + char *filename; + char name_buffer[PTFPARSER_NAMEBUFSIZE]; + int name_length; + char value_buffer[PTFPARSER_VALUEBUFSIZE]; + int value_length; + struct + { + unsigned error:1; + unsigned escaped:1; + unsigned single_quoted:1; + unsigned double_quoted:1; + } flag; + + enum + { + section_or_item_specification, + more_section_type_or_item_name_chars, + whitespace_after_section_specification, + whitespace_after_section_or_item_name, + whitespace_before_item_value, + more_section_name_chars, + more_item_value_chars, + } expectation; +}; + +/***************************************************************************/ +struct ptf *ptf_alloc_item(ptf_item_type t, char *name, char *value) +{ + struct ptf *new_item; + new_item = (struct ptf *)malloc(sizeof(struct ptf)); + if(!new_item) return NULL; + + new_item->type = t; + new_item->sub = NULL; + new_item->next = NULL; + new_item->name = NULL; + new_item->value = NULL; + + if(name != NULL) + { + int n = strlen(name); + if(n > 0) + { + new_item->name = (char *)malloc(n + 1); + if(new_item->name == NULL) + { + free(new_item); + return NULL; + }; + strcpy(new_item->name, name); + } + }; + + if(value != NULL) + { + int n = strlen(value); + if(n > 0) + { + new_item->value = (char *)malloc(n + 1); + if(new_item->value == NULL) + { + if(name != NULL) free(new_item->name); + free(new_item); + return NULL; + }; + strcpy(new_item->value, value); + }; + }; + + return new_item; +} + +/***************************************************************************/ +void add_ptf_item(struct ptf_parser_state *state, struct ptf *item) +{ + if(state->current_item == NULL) + { + if(state->section_level > 0) + state->current_in[state->section_level-1]->sub = item; + else + state->tree = item; + } + else + state->current_item->next = item; +} + + +/***************************************************************************/ +void parse_error(struct ptf_parser_state *state, char *errmsg) +{ + fprintf(stderr, "Error while parsing %s (line %lu): %s\n", + state->filename, state->line, errmsg); + + state->flag.error = 1; +} + +/***************************************************************************/ +void init_parser(struct ptf_parser_state *state, char *filename) +{ + int i; + + state->line = 1; + state->flag.error = 0; + state->flag.escaped = 0; + state->flag.double_quoted = 0; + state->flag.single_quoted = 0; + state->section_level = 0; + + state->filename = (char *)malloc(strlen(filename)+1); + if(state->filename != NULL) strcpy(state->filename, filename); + + state->expectation = section_or_item_specification; + + state->tree = NULL; + state->current_item = NULL; + for(i=1; icurrent_in[i] = NULL; +} + +/***************************************************************************/ +void ptf_free(struct ptf *ptf) +{ + struct ptf *this, *next; + for(this = ptf; this != NULL; this = next) + { + next = this->next; + if(this->value != NULL) free(this->value); + if(this->name != NULL) free(this->name); + if(this->type == section) ptf_free(this->sub); + free(this); + }; +} + +/***************************************************************************/ +void abort_parsing(struct ptf_parser_state *state) +{ + if(state->filename != NULL) free(state->filename); + ptf_free(state->tree); +} + +/***************************************************************************/ +int add_char_to_buffer(int *len, char *buf, int maxlen, char c) +{ + if(*len >= maxlen) return 0; + + buf[(*len)++] = c; + + return 1; +} + +/***************************************************************************/ +void parse_char(struct ptf_parser_state *state, int c) +{ + int is_not_quoted; + int is_no_space; + enum { item_parsed, section_opened, section_closed, none } parser_event; + + switch(c) + { + case '\\': + { + if(state->flag.escaped == 0) + { + state->flag.escaped = 1; + return; + }; + break; + }; + case '"': + { + if(!state->flag.escaped && !state->flag.single_quoted) + { + state->flag.double_quoted = 1 - state->flag.double_quoted; + return; + } + break; + }; + case '\'': + { + if(!state->flag.escaped && !state->flag.double_quoted) + { + state->flag.single_quoted = 1 - state->flag.single_quoted; + return; + } + break; + }; + case '\n': + { + state->line++; + break; + }; + default: + break; + }; + + parser_event = none; + + is_not_quoted = !(state->flag.escaped || + state->flag.single_quoted || state->flag.double_quoted); + is_no_space = (!is_not_quoted || !isspace(c)); + state->flag.escaped = 0; + + switch(state->expectation) + { + case section_or_item_specification: + { +#if DEBUG&DEBUG_EXPECTATIONS + printf("Expectation: section_or_item_specification\n"); +#endif + + if(is_not_quoted && c == '}') + { + parser_event = section_closed; + } + else if(is_no_space) + { + state->name_length = 1; + state->name_buffer[0] = c; + state->expectation = more_section_type_or_item_name_chars; + }; + break; + }; + + case more_section_type_or_item_name_chars: + { +#if DEBUG&DEBUG_EXPECTATIONS + printf("Expectation: more_section_type_or_item_name_chars\n"); +#endif + + /* Item name is stored in name_buffer */ + /* Section type is stored in name_buffer */ + if(is_no_space) + { + if(!add_char_to_buffer(&state->name_length, state->name_buffer, PTFPARSER_NAMEBUFSIZE, c)) + parse_error(state, "First word is too long; I expected a shorter section type or item name"); + } + else + { + state->expectation = whitespace_after_section_or_item_name; + } + break; + }; + + case whitespace_after_section_specification: + { +#if DEBUG&DEBUG_EXPECTATIONS + printf("Expectation: whitespace_after_section_specification\n"); +#endif + + if(c == '{') + parser_event = section_opened; + else if(is_no_space) + parse_error(state, "Expected section content within brackets {...}"); + break; + }; + + case whitespace_after_section_or_item_name: + { +#if DEBUG&DEBUG_EXPECTATIONS + printf("Expectation: whitespace_after_section_or_item_name\n"); +#endif + + if(c == '{') + { + state->value_length = 0; + parser_event = section_opened; + } + else if(c == '=') + state->expectation = whitespace_before_item_value; + else if(is_no_space) + { + state->value_length = 1; + state->value_buffer[0] = c; + state->expectation = more_section_name_chars; + }; + break; + }; + + case more_section_name_chars: + { +#if DEBUG&DEBUG_EXPECTATIONS + printf("Expectation: more_section_name_chars\n"); +#endif + + /* Section name is stored in value_buffer */ + if(is_no_space) + { + if(!add_char_to_buffer(&state->value_length, state->value_buffer, PTFPARSER_VALUEBUFSIZE, c)) + parse_error(state, "Section name is too long"); + } + else + state->expectation = whitespace_after_section_specification; + break; + } + + case whitespace_before_item_value: + { +#if DEBUG&DEBUG_EXPECTATIONS + printf("Expectation: whitespace_before_item_value\n"); +#endif + + if(is_not_quoted && c == ';') + { + state->value_length = 0; + parser_event = item_parsed; + } + else if(is_no_space) + { + state->value_length = 1; + state->value_buffer[0] = c; + state->expectation = more_item_value_chars; + }; + break; + }; + + case more_item_value_chars: + { +#if DEBUG&DEBUG_EXPECTATIONS + printf("Expectation: more_item_value_chars\n"); +#endif + + /* Item value is stored in value_buffer */ + if(is_not_quoted && c == ';') + parser_event = item_parsed; + else if(is_no_space) + { + if(!add_char_to_buffer(&state->value_length, state->value_buffer, PTFPARSER_VALUEBUFSIZE, c)) + parse_error(state, "Item value is too long"); + } + else + parser_event = item_parsed; + break; + } + + default: +#if DEBUG&DEBUG_EXPECTATIONS + printf("Expectation: %d (?)\n", state->expectation); +#endif + + parse_error(state, "Internal error: Unhandled state of expectation"); + }; + + switch(parser_event) + { + /* TODO: pointer tuff */ + + case item_parsed: + { + struct ptf *new_item; + state->name_buffer[state->name_length] = 0; + state->value_buffer[state->value_length] = 0; +#if DEBUG&DEBUG_READVALUES + printf("== Item %s is '%s' ==\n", state->name_buffer, state->value_buffer); +#endif + + new_item = ptf_alloc_item(item, state->name_buffer, state->value_buffer); + if(new_item == NULL) + { + parse_error(state, "Internal error: " + "Could not allocate memory for new item"); + return; + }; + + add_ptf_item(state, new_item); + state->current_item = new_item; + state->expectation = section_or_item_specification; + + break; + }; + case section_opened: + { + struct ptf *new_section; + state->name_buffer[state->name_length] = 0; + state->value_buffer[state->value_length] = 0; +#if DEBUG&DEBUG_READVALUES + printf("== New %s section '%s' opened ==\n", state->name_buffer, state->value_buffer); +#endif + + if(state->section_level >= PTFPARSER_MAXDEPTH-1) + { + parse_error(state, "Internal error: " + "cannot handle sections nested as deep as here."); + return; + }; + + new_section = ptf_alloc_item(section, state->name_buffer, state->value_buffer); + if(new_section == NULL) + { + parse_error(state, "Internal error: " + "Could not allocate memory for new section"); + return; + }; + + add_ptf_item(state, new_section); + state->current_item = NULL; + state->current_in[state->section_level] = new_section; + state->section_level++; + + state->expectation = section_or_item_specification; + break; + }; + case section_closed: + { + if(state->section_level < 1) + { + parse_error(state, "Found closing '}' without opening '{' before"); + return; + }; + + state->section_level--; + state->current_item = state->current_in[state->section_level]; + state->expectation = section_or_item_specification; +#if DEBUG&DEBUG_READVALUES + printf("-- Closed section --\n"); +#endif + break; + }; + default: + break; + }; +} + +/***************************************************************************/ +struct ptf *ptf_parse_file(char *filename) +{ + FILE *f; + char buffer[1024]; + + struct ptf *root; + struct ptf_parser_state state; + + if(filename == NULL) + { + fprintf(stderr, "Internal error: " + "No filename was given to ptf_read()\n"); + return NULL; + }; + + f = fopen(filename, "r"); + if(f == NULL) + { + perror(filename); + return NULL; + }; + + init_parser(&state, filename); + + while(!feof(f)) + { + size_t r, n; + + if(ferror(f)) + { + perror(filename); + abort_parsing(&state); + fclose(f); + return NULL; + }; + + n = fread(buffer, 1, 1024, f); + for(r=0; rnext != NULL; leaf = leaf->next); + leaf->next = b; + return a; +} + +/***************************************************************************/ + +void ptf_dump_ptf_item(FILE *f, struct ptf_item *pi) +{ + int i; + fprintf(f, "level=%d in %p\n", pi->level, pi); + for(i=pi->level;i>=0;i--) + { + if(pi->item[i] != NULL) + { + fprintf(f, " %d: %s name=%s value=%s\n", + i, + pi->item[i]->type == item ? "item":"section", + pi->item[i]->name, + pi->item[i]->value); + } + else + { + fprintf(f, " %d: NULL\n"); + } + fflush(f); + } +} + +/***************************************************************************/ + +void ptf_printf(FILE *s, struct ptf *tree, char *prefix) +{ + struct ptf *leaf; + + for(leaf = tree; leaf != NULL; leaf = leaf->next) + { + switch(leaf->type) + { + case section: + { + char *new_prefix; + int new_prefix_len; + new_prefix_len = strlen(prefix) + strlen(leaf->name) + 2; + if(leaf->value != NULL && leaf->value[0] != 0) + { + new_prefix_len += strlen(leaf->value) + 1; + }; + new_prefix = (char *)malloc(new_prefix_len); + strcpy(new_prefix, prefix); + strcat(new_prefix, leaf->name); + if(leaf->value != NULL && leaf->value[0] != 0) + { + strcat(new_prefix, ":"); + strcat(new_prefix, leaf->value); + }; + strcat(new_prefix, "/"); + fputs(new_prefix, s); + fputs("\n", s); + ptf_printf(s, leaf->sub, new_prefix); + break; + }; + + case item: + { + char *c; + fputs(prefix, s); + fputs(leaf->name, s); + fputs(" = \"", s); + if(leaf->value == NULL) + { + fputs("(NULL)", s); + } + else + { + for(c=leaf->value; *c; c++) + { + if(*c=='\\' || *c=='"') putc('\\', s); + putc(*c, s); + }; + } + fprintf(s, "\"\n"); + break; + }; + + default: + break; + }; + }; +} + +/***************************************************************************/ + +int ptf_advance_one(struct ptf_item *item) +{ + int d; + struct ptf *leaf; + + d = item->level; + leaf = item->item[d]; + + if(leaf != NULL) + { + if(leaf->type == section && leaf->sub != NULL) + { + if(item->level >= MAX_SECTION_NESTING-1) + { + /* raise an error? hm, for now we silently ignore the subtree */ + } + else + { + d++; + item->item[d] = leaf->sub; + item->level = d; + return 0; + } + } + item->item[item->level] = leaf->next; + }; + + while(item->item[d] == NULL) + { + if(d == 0) + { + item->level = 0; + item->item[0] = NULL; + errno = ENOENT; + return -1; + } + d --; + leaf = item->item[d]; + if(leaf != NULL) item->item[d] = leaf->next; + }; + + item->level = d; + return 0; +} + +/***************************************************************************/ + +int ptf_advance_until( + struct ptf_item *item, + ptf_item_type ttype, + char *name, + char *value) +{ + int r; + struct ptf *leaf; + + do + { + leaf = item->item[item->level]; +#if DEBUG&DEBUG_FINDER + printf(" Does %s/%s match %s/%s?\n", leaf->name, leaf->value, name, value); +#endif + + if(leaf->type == ttype) + { + if(name == NULL) + { + if(value == NULL) + { + return 0; /* got it (any value) */ + } + else if (leaf->value != NULL) + { + if(strcmp(leaf->value, value) == 0) return 0; /* got it */ + } + } + else if(leaf->name != NULL) + { + if(strcmp(leaf->name, name) == 0) + { + if(value == NULL) + { + return 0; /* got it (any value) */ + } + else if(leaf->value != NULL) + { + if(strcmp(leaf->value, value) == 0) return 0; /* got it */ + } + } + } + }; + r = ptf_advance_one(item); + + } while(r == 0); + + return r; +} + +/***************************************************************************/ + +struct ptf *ptf_find( + struct ptf *tree, + struct ptf_item *item, + ptf_item_type ttype, + char *name, + char *value) +{ + int r; + + if(item == NULL) { errno = EINVAL; return NULL; }; + if(tree == NULL) { errno = ENOENT; return NULL; }; + + item->level = 0; + item->item[0] = tree; + + if(ptf_advance_until(item, ttype, name, value) != 0) return NULL; + + r = item->level; + item->level++; /* To match ptf_match */ + return item->item[r]; +} + +/***************************************************************************/ + +struct ptf *ptf_next( + struct ptf_item *item, + ptf_item_type ttype, + char *name, + char *value) +{ + int r; + struct ptf *leaf; + + if(item == NULL) { errno = EINVAL; return NULL; }; + + if(item->level < 1) return NULL; + item->level--; /* To match ptf_match */ + + r = ptf_advance_one(item); + + if(r == 0) r = ptf_advance_until(item, ttype, name, value); + + if(r != 0) return NULL; + + r = item->level; + item->level++; /* To match ptf_match */ + return item->item[r]; +} + +/***************************************************************************/ + +int ptf_match( + struct ptf *const ptf, + struct ptf_item *const match, + const ptf_match_action action, + void *arg) +{ + int count; + struct ptf *p; + struct ptf_item pi; + + p = ptf; + count = 0; + pi.level = 0; + + while(p != NULL) + { + ptf_item_type mtype = match->item[pi.level]->type; + char *mname = match->item[pi.level]->name; + char *mvalue = match->item[pi.level]->value; + +#if DEBUG&DEBUG_FINDER + printf("Looking for %s/%s, checking %s/%s\n", + mname, mvalue, p->name, p->value); +#endif + + if(mtype == p->type && + (mname==NULL || p->name==NULL || strcmp(mname, p->name)==0) && + (mvalue==NULL || p->value==NULL || strcmp(mvalue, p->value)==0)) + { + pi.item[pi.level] = p; + + if(pi.level == match->level - 1) + { + if(action != NULL) action(&pi, arg); + p = p->next; + count++; + } + else + { + if(p->sub != NULL && pi.level < MAX_SECTION_NESTING-1) + { + pi.item[pi.level] = p; + pi.level++; + p = p->sub; + } + else + { + p = p->next; + }; + }; + } + else + { + p = p->next; + }; + + while(p == NULL && pi.level > 0) + { + pi.level--; + p = pi.item[pi.level]->next; + }; + }; + return count; +} + +/***************************************************************************/ + +char *ptf_defused_name(char *orig_name) +{ + int i,j; + char *s = (char *)malloc(1+strlen(orig_name)); + + if(!s) return NULL; + + for(i=j=0;orig_name[i];i++) + { + if(!isalnum(orig_name[i])) + { + if(j>0) if(s[j-1]!='_') s[j++]='_'; + } + else + { + s[j++] = toupper(orig_name[i]); + }; + }; + s[j] = 0; + return s; +} + diff --git a/tools/cpu/nios2/ptf.h b/tools/cpu/nios2/ptf.h new file mode 100644 index 0000000000..c847cf3b1f --- /dev/null +++ b/tools/cpu/nios2/ptf.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if !defined(__PTF_H) +#define __PTF_H 1 + +#include + +#define MAX_SECTION_NESTING 20 + +typedef enum +{ + item, section +} +ptf_item_type; + +struct ptf +{ + ptf_item_type type; + char *name; + char *value; + struct ptf *sub; + struct ptf *next; +}; + +struct ptf_item +{ + int level; + struct ptf *item[MAX_SECTION_NESTING]; +}; + + +typedef void (*ptf_match_action)(struct ptf_item *x, void *arg); + +struct ptf *ptf_parse_file(char *filename); +struct ptf *ptf_concat(struct ptf *a, struct ptf *b); +struct ptf *ptf_alloc_item(ptf_item_type t, char *name, char *value); +void ptf_printf(FILE *s, struct ptf *tree, char *prefix); +void ptf_dump_ptf_item(FILE *s, struct ptf_item *pi); + +struct ptf *ptf_find( + struct ptf *tree, + struct ptf_item *item, + ptf_item_type ttype, + char *name, + char *value); + +struct ptf *ptf_next( + struct ptf_item *item, + ptf_item_type ttype, + char *name, + char *value); + +int ptf_match( + struct ptf *const ptf, + struct ptf_item *const match, + const ptf_match_action action, + void *arg); + +char *ptf_defused_name(char *); + + +#endif /* !defined(__PTF_H) */ + diff --git a/tools/cpu/nios2/sample.ptf b/tools/cpu/nios2/sample.ptf new file mode 100644 index 0000000000..eb4cf7fea4 --- /dev/null +++ b/tools/cpu/nios2/sample.ptf @@ -0,0 +1,462 @@ +N2GCOMM = "=============== Header output settings ==========================="; + +BSPHEADER +{ + LEADTEXT = +"/* Autogenerated by nios2gen, (C) 2006 K. Waschk rtemsdev/ixo.de */ + +#ifndef __SOPC_H +#define __SOPC_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define CLOCK_FREQ_REF(clock) clock ## _FREQ +#define CLOCK_FREQ(x) CLOCK_FREQ_REF(x) + +"; + + EPILOG = +" +#ifdef __cplusplus +} +#endif +#endif +"; +} + +N2GCOMM = "=============== Class templates =================================="; + +CLASS altera_nios2 +{ + N2G_DEFINE_IS_AVAILABLE = "1"; + + SYSTEM_BUILDER_INFO + { + Clock_Source = "N2G_CLOCKREF_CLOCK"; + } + SLAVE jtag_debug_module + { + SYSTEM_BUILDER_INFO { Base_Address = "BASE_ADDR"; } + } + WIZARD_SCRIPT_ARGUMENTS + { + cache_has_dcache = "HAS_DCACHE"; + cache_has_icache = "HAS_ICACHE"; + cache_dcache_size = "DCACHE_SIZE"; + cache_icache_size = "ICACHE_SIZE"; + cache_dcache_line_size = "DCACHE_LINE_SIZE"; + cache_icache_line_size = "ICACHE_LINE_SIZE"; + cache_dcache_bursts = "DCACHE_BURSTS"; + cache_icache_burst_type = "ICACHE_BURST_TYPE"; + hardware_multiply_present = "HAS_HWMULT"; + } +} + +CLASS altera_avalon_onchip_memory2 +{ + N2G_DEFINE_IS_AVAILABLE = "1"; + + WIZARD_SCRIPT_ARGUMENTS + { + Writeable = "WRITEABLE"; + dual_port = "DUAL_PORT"; + Size_Value = "SIZE_VALUE"; + Size_Multiple = "SIZE_MULTIPLE"; + } + SYSTEM_BUILDER_INFO + { + Clock_Source = "N2G_CLOCKREF_CLOCK"; + } + SLAVE s1 + { + N2G_DEFINE_CONNECTED_PORT = "S1"; + + SYSTEM_BUILDER_INFO + { + Base_Address = "S1_BASE_ADDR"; + Data_Width = "S1_DATA_WIDTH"; + Address_Width = "S1_ADDR_WIDTH"; + Address_Span = "S1_ADDR_SPAN"; + } + } + SLAVE s2 + { + N2G_DEFINE_CONNECTED_PORT = "S2"; + + SYSTEM_BUILDER_INFO + { + Base_Address = "S2_BASE_ADDR"; + Data_Width = "S2_DATA_WIDTH"; + Address_Width = "S2_ADDR_WIDTH"; + Address_Span = "S2_ADDR_SPAN"; + } + } +} + +CLASS sram_256k_x_16_bit +{ + N2G_DEFINE_IS_AVAILABLE = "1"; + + SLAVE sram + { + SYSTEM_BUILDER_INFO + { + Base_Address = "BASE_ADDR"; + Data_Width = "DATA_WIDTH"; + Address_Width = "ADDR_WIDTH"; + Address_Span = "ADDR_SPAN"; + } + } +} + +CLASS altera_avalon_sysid +{ + N2G_DEFINE_IS_AVAILABLE = "1"; + + SLAVE control_slave + { + SYSTEM_BUILDER_INFO + { + Base_Address = "BASE_ADDR"; + } + } + WIZARD_SCRIPT_ARGUMENTS + { + id = "ID"; + timestamp = "TIMESTAMP"; + } +} + +CLASS altera_avalon_timer +{ + N2G_DEFINE_IS_AVAILABLE = "1"; + + SLAVE s1 + { + SYSTEM_BUILDER_INFO + { + Base_Address = "BASE_ADDR"; + IRQ_MASTER { IRQ_Number = "IRQ"; } + } + } + WIZARD_SCRIPT_ARGUMENTS + { + snapshot = "SNAPSHOT"; + always_run = "ALWAYS_RUN"; + mult = "MULT"; + period = "PERIOD"; + period_units = "PERIOD_UNITS"; + fixed_period = "FIXED_PERIOD"; + } + SYSTEM_BUILDER_INFO + { + Clock_Source = "N2G_CLOCKREF_CLOCK"; + } +} + + +CLASS altera_avalon_uart +{ + N2G_DEFINE_IS_AVAILABLE = "1"; + + SYSTEM_BUILDER_INFO + { + Clock_Source = "N2G_CLOCKREF_CLOCK"; + } + WIZARD_SCRIPT_ARGUMENTS + { + use_cts_rts = "USE_CTS_RTS"; + use_eop_register = "USE_EOP_REG"; + } + SLAVE s1 + { + SYSTEM_BUILDER_INFO + { + Base_Address = "BASE_ADDR"; + IRQ_MASTER { IRQ_Number = "IRQ"; } + } + } +} + +CLASS altera_avalon_jtag_uart +{ + N2G_DEFINE_IS_AVAILABLE = "1"; + + SLAVE avalon_jtag_slave + { + SYSTEM_BUILDER_INFO + { + Base_Address = "BASE_ADDR"; + IRQ_MASTER { IRQ_Number = "IRQ"; } + } + } +} + +CLASS altera_avalon_pio +{ + N2G_DEFINE_IS_AVAILABLE = "1"; + + SYSTEM_BUILDER_INFO + { + Clock_Source = "N2G_CLOCKREF_CLOCK"; + } + SLAVE + { + SYSTEM_BUILDER_INFO + { + Base_Address = "BASE_ADDR"; + IRQ_MASTER { IRQ_Number = "IRQ"; } + } + } +} + +N2GCOMM = "=============== Linkcmds output settings ========================="; + +LINKCMDS +{ + LEADTEXT = " +OUTPUT_FORMAT( "elf32-littlenios2", + "elf32-littlenios2", + "elf32-littlenios2" ) +OUTPUT_ARCH( nios2 ) +ENTRY( _start ) +" + + SECTION entry + { + COMMANDS = +" KEEP (*(.entry)) +"; + } + + SECTION exceptions + { + COMMANDS = +" PROVIDE (__ram_exceptions_start = ABSOLUTE(.)); + . = ALIGN(0x20); + *(.irq) + KEEP (*(.exceptions.entry.label)); + KEEP (*(.exceptions.entry.user)); + KEEP (*(.exceptions.entry)); + KEEP (*(.exceptions.irqtest.user)); + KEEP (*(.exceptions.irqtest)); + KEEP (*(.exceptions.irqhandler.user)); + KEEP (*(.exceptions.irqhandler)); + KEEP (*(.exceptions.irqreturn.user)); + KEEP (*(.exceptions.irqreturn)); + KEEP (*(.exceptions.notirq.label)); + KEEP (*(.exceptions.notirq.user)); + KEEP (*(.exceptions.notirq)); + KEEP (*(.exceptions.soft.user)); + KEEP (*(.exceptions.soft)); + KEEP (*(.exceptions.unknown.user)); + KEEP (*(.exceptions.unknown)); + KEEP (*(.exceptions.exit.label)); + KEEP (*(.exceptions.exit.user)); + KEEP (*(.exceptions.exit)); + KEEP (*(.exceptions)); + PROVIDE (__ram_exceptions_end = ABSOLUTE(.)); +"; + } + + SECTION text + { + LOCATION = "SDRAM"; + COMMANDS = +" PROVIDE (stext = ABSOLUTE(.)); + + *(.interp) + *(.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.rel.init) + *(.rela.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rel.fini) + *(.rela.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rela.ctors) + *(.rel.dtors) + *(.rela.dtors) + *(.rel.got) + *(.rela.got) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rel.plt) + *(.rela.plt) + + KEEP (*(.init)) + *(.plt) + *(.text .stub .text.* .gnu.linkonce.t.*) + + /* Special FreeBSD sysctl sections. */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + *(.gnu.warning.*) + KEEP (*(.fini)) + PROVIDE (__etext = ABSOLUTE(.)); + PROVIDE (_etext = ABSOLUTE(.)); + PROVIDE (etext = ABSOLUTE(.)); + + *(.eh_frame_hdr) + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = ABSOLUTE(.)); + *(.preinit_array) + PROVIDE (__preinit_array_end = ABSOLUTE(.)); + PROVIDE (__init_array_start = ABSOLUTE(.)); + *(.init_array) + PROVIDE (__init_array_end = ABSOLUTE(.)); + PROVIDE (__fini_array_start = ABSOLUTE(.)); + *(.fini_array) + PROVIDE (__fini_array_end = ABSOLUTE(.)); + SORT(CONSTRUCTORS) + KEEP (*(.eh_frame)) + *(.gcc_except_table) + *(.dynamic) + PROVIDE (__CTOR_LIST__ = ABSOLUTE(.)); + KEEP (*(.ctors)) + KEEP (*(SORT(.ctors.*))) + PROVIDE (__CTOR_END__ = ABSOLUTE(.)); + PROVIDE (__DTOR_LIST__ = ABSOLUTE(.)); + KEEP (*(.dtors)) + KEEP (*(SORT(.dtors.*))) + PROVIDE (__DTOR_END__ = ABSOLUTE(.)); + KEEP (*(.jcr)) + . = ALIGN(32 / 8); +"; + } + + SECTION rodata + { + LOCATION = "SDRAM"; + COMMANDS = +" PROVIDE (__ram_rodata_start = ABSOLUTE(.)); + . = ALIGN(32 / 8); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + . = ALIGN(32 / 8); + PROVIDE (__ram_rodata_end = ABSOLUTE(.)); +"; + } + + SECTION rwdata + { + LOCATION = "SDRAM"; + COMMANDS = +" PROVIDE (__ram_rwdata_start = ABSOLUTE(.)); + . = ALIGN(32 / 8); + *(.got.plt) *(.got) + *(.data1) + *(.data .data.* .gnu.linkonce.d.*) + + _gp = ABSOLUTE(. + 0x8000); + PROVIDE(gp = _gp); + + *(.sdata .sdata.* .gnu.linkonce.s.*) + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + + . = ALIGN(32 / 8); + _edata = ABSOLUTE(.); + PROVIDE (edata = ABSOLUTE(.)); + PROVIDE (__ram_rwdata_end = ABSOLUTE(.)); +"; + } + + SECTION bss + { + LOCATION = "SDRAM"; + COMMANDS = +" __bss_start = ABSOLUTE(.); + PROVIDE (__sbss_start = ABSOLUTE(.)); + PROVIDE (___sbss_start = ABSOLUTE(.)); + + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + *(.scommon) + + PROVIDE (__sbss_end = ABSOLUTE(.)); + PROVIDE (___sbss_end = ABSOLUTE(.)); + + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + + . = ALIGN(32 / 8); + __bss_end = ABSOLUTE(.); +"; + } + + STABS = +" .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /* Altera debug extensions */ + .debug_alt_sim_info 0 : { *(.debug_alt_sim_info) } +"; + + HEAP = "SDRAM"; + STACK = "SDRAM"; +} + diff --git a/tools/cpu/sh/.cvsignore b/tools/cpu/sh/.cvsignore new file mode 100644 index 0000000000..bfdfd995be --- /dev/null +++ b/tools/cpu/sh/.cvsignore @@ -0,0 +1,14 @@ +aclocal.m4 +autom4te*.cache +config.cache +config.guess +config.log +config.status +config.sub +configure +depcomp +install-sh +Makefile +Makefile.in +missing +mkinstalldirs diff --git a/tools/cpu/sh/AUTHORS b/tools/cpu/sh/AUTHORS new file mode 100644 index 0000000000..225c2fa974 --- /dev/null +++ b/tools/cpu/sh/AUTHORS @@ -0,0 +1,3 @@ +Ralf Corsepius (corsepiu@faw.uni-ulm.de) + * Initial implementation + * generator for sci bitrate table diff --git a/tools/cpu/sh/COPYING b/tools/cpu/sh/COPYING new file mode 100644 index 0000000000..01e8961d69 --- /dev/null +++ b/tools/cpu/sh/COPYING @@ -0,0 +1,343 @@ +# +# $Id$ +# + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tools/cpu/sh/ChangeLog b/tools/cpu/sh/ChangeLog new file mode 100644 index 0000000000..f9eae7b598 --- /dev/null +++ b/tools/cpu/sh/ChangeLog @@ -0,0 +1,86 @@ +2011-02-02 Ralf Corsépius + + * configure.ac: Require autoconf-2.68, automake-1.11.1. + +2006-12-02 Ralf Corsépius + + * configure.ac: New BUG-REPORT address. + +2006-10-17 Ralf Corsépius + + * configure.ac: Require autoconf-2.60. Require automake-1.10. + +2006-01-31 Ralf Corsepius + + * shgen.c: include . + +2004-09-24 Ralf Corsepius + + * configure.ac: Require automake > 1.9. + +2004-01-06 Ralf Corsepius + + * Makefile.am: Let shgen.1 depend on shgen$(EXEEXT). + +2003-12-12 Ralf Corsepius + + * configure.ac: Require automake >= 1.8, autoconf >= 2.59. + +2003-08-11 Ralf Corsepius + + * configure.ac: Use rtems-bugs@rtems.com as bug report email address. + +2003-03-06 Ralf Corsepius + + * configure.ac: Remove AC_CONFIG_AUX_DIR. + +2003-02-11 Ralf Corsepius + + * configure.ac: AM_INIT_AUTOMAKE([1.7.2]). + +2003-02-11 Ralf Corsepius + + * configure.ac: AC_PREREQ(2.57). + +2002-10-21 Ralf Corsepius + + * .cvsignore: Reformat. + Add autom4te*cache. + Remove autom4te.cache. + +2002-04-01 Ralf Corsepius + + * configure.ac: Remove AC_EXEEXT (obsolete). + +2002-03-27 Ralf Corsepius + + * configure.ac: + AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS). + AM_INIT_AUTOMAKE([no-define foreign 1.6]). + * Makefile.am: Remove AUTOMAKE_OPTIONS. + +2001-10-11 Ralf Corsepius + + * .cvsignore: Add autom4te.cache for autoconf > 2.52. + * configure.in: Remove. + * configure.ac: New file, generated from configure.in by autoupdate. + +2000-11-13 Ralf Corsepius + + * shgen.c: Set default Phi to 20MHz (BUG-FIX). + +2000l-11-09 Ralf Corsepius + + * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS. + +2000-11-02 Ralf Corsepius + + * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal. + +2000-10-30 Ralf Corsepius + + * Makefile.am: Switch to GNU-canonicalized autoconf macros. + +2000-08-10 Joel Sherrill + + * ChangeLog: New file. diff --git a/tools/cpu/sh/Makefile.am b/tools/cpu/sh/Makefile.am new file mode 100644 index 0000000000..be30a63c12 --- /dev/null +++ b/tools/cpu/sh/Makefile.am @@ -0,0 +1,18 @@ +## +## $Id$ +## + +ACLOCAL_AMFLAGS = -I ../../../aclocal + +noinst_PROGRAMS = shgen + +shgen_SOURCES = sci.h sci.c shgen.c + +if HELP2MAN +man_MANS = shgen.1 + +shgen.1: shgen$(EXEEXT) + $(HELP2MAN) -N ./shgen >$@ +endif + +include $(top_srcdir)/../../../automake/host.am diff --git a/tools/cpu/sh/TODO b/tools/cpu/sh/TODO new file mode 100644 index 0000000000..bcdd1bf6df --- /dev/null +++ b/tools/cpu/sh/TODO @@ -0,0 +1,13 @@ +* Add support for more drivers to shgen !!!! + +* shgen relies on having a gnu-compatible getopt, which should be + available on all hosts using gcc/egcs/binutils. + Using other getopt-variants may produce faulty results or shgen may also + refuse to compile. Probably the easiest solution to this problem would be + to integrate libiberty into rtems. + +* shgen uses floating point mathematics. Therefore Makefile.in contains a + reference to libm. In case the host doesn't have its floating point + support in libm, shgen will fail to compile. If we should ever meet such + a host, checks for floating point libraries have to be added to rtems' + autoconf support. diff --git a/tools/cpu/sh/configure.ac b/tools/cpu/sh/configure.ac new file mode 100644 index 0000000000..82fae15f96 --- /dev/null +++ b/tools/cpu/sh/configure.ac @@ -0,0 +1,25 @@ +## Process this file with autoconf to produce a configure script. +## +## $Id$ + +AC_PREREQ([2.68]) +AC_INIT([rtems-tools-cpu-sh],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([shgen.c]) +RTEMS_TOP(../../..) + +RTEMS_CANONICAL_TARGET_CPU + +AM_INIT_AUTOMAKE([foreign 1.11.1]) +AM_MAINTAINER_MODE + +AC_PROG_CC +AC_CHECK_LIB(m,fabs) +AC_CHECK_FUNCS(getopt_long) +AC_CHECK_PROGS(HELP2MAN,help2man) +AM_CONDITIONAL(HELP2MAN,test -n "$HELP2MAN" ) + +RTEMS_TOOLPATHS + +# Explicitly list all Makefiles here +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/tools/cpu/sh/sci.c b/tools/cpu/sh/sci.c new file mode 100644 index 0000000000..bc7fdd83a8 --- /dev/null +++ b/tools/cpu/sh/sci.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1998 Ralf Corsepius (corsepiu@faw.uni-ulm.de) + * + * See the file COPYING for copyright notice. + */ + +#include +#include +#include + +#include "sci.h" + +/* + n .. baudrate generator source 0,1,2,3 + + N .. BRR setting (0..255) + + Phi .. processor baud rate + + B .. bitrate + */ + +typedef struct sci_tab { + unsigned int B ; + unsigned int n ; + int N ; + double err ; + } sci_tab_t ; + +static unsigned int bitrate [] = { + 50, + 75, + 110, + 134, + 150, + 200, + 300, + 600, + 1200, + 1800, + 2400, + 4800, + 9600, + 19200, + 38400, + 57600, + 115200, + 230400, + 460800 +}; + +static sci_tab_t test_array[4] ; + +static void Compute( + unsigned int n, + unsigned int B, + double Phi, + struct sci_tab *entry ) +{ + int a = ( 32 << ( 2 * n ) ) * B ; + + entry->n = n ; + entry->B = B ; + entry->N = rint( ( Phi / a ) - 1.0 ) ; + + if ( ( entry->N > 0 ) && ( entry->N < 256 ) ) + entry->err = + ( ( Phi / ( (entry->N + 1) * a ) - 1.0 ) * 100.0 ); + else + { + entry->err = 100.0 ; + entry->n = 255 ; + entry->N = 0 ; + } +} + +static sci_tab_t *SelectN( + unsigned int B, + double Phi ) +{ + unsigned int i ; + struct sci_tab* best = NULL ; + + for ( i = 0 ; i < 4 ; i++ ) + { + double err ; + + Compute( i, B, Phi, &test_array[i] ); + err = fabs( test_array[i].err ); + + if ( best ) + { + if ( err < fabs( best->err ) ) + best = &test_array[i] ; + } + else + best = &test_array[i] ; + } + + return best ; +} + +int shgen_gensci( + FILE *file, + double Phi ) /* Processor frequency [Hz] */ +{ + unsigned int i ; + + fprintf( file, + "/*\n * Bitrate table for the serial devices (sci) of the SH at %.3f MHz\n" + " */\n\n", Phi / 1000000.0 ); + fprintf( file, + "/*\n" + " * n .. SMR bits 0,1 : baud rate generator clock source\n" + " * N .. BRR bits 0..7: setting for baud rate generator\n" + " * error .. percentual error to nominal bitrate\n" + " * Hitachi's HW manual recommends bitrates with an error less than 1%%\n" + " * We experienced values less than 2%% to be stable\n" + " */\n\n" ); + fprintf( file, "#include \n\n" ); + fprintf( file, + "static struct sci_bitrate_t {\n" + " unsigned char n ;\n" + " unsigned char N ;\n" + "} _sci_bitrates[] = {\n" + "/* n N error */\n" ); + + for ( i = 0 ; i < sizeof(bitrate)/sizeof(int) ; i++ ) + { + struct sci_tab* best = SelectN( bitrate[i], Phi ); + + if ( i > 0 ) + fprintf( file, ",\n" ); + fprintf( file, " { %1d, %3d } /* %+7.2f%% ; B%d ", + best->n, + best->N, + best->err, + best->B ); + if ( best->n > 3 ) + fprintf( file, "(unusable) " ); + fprintf( file, "*/" ); + } + + fprintf( file, "\n};\n\n" ); + + fprintf( file, + "int _sci_get_brparms( \n" + " tcflag_t cflag,\n" + " unsigned char *smr,\n" + " unsigned char *brr )\n" + "{\n" + " unsigned int offset ;\n\n" + " offset = ( cflag & ( CBAUD & ~CBAUDEX ) )\n" + " + ( ( cflag & CBAUDEX ) ? B38400 : 0 );\n" + " if ( offset == 0 ) return -1 ;\n" + " offset-- ;\n\n" + " if ( _sci_bitrates[offset].n > 3 ) return -1;\n\n" + " *smr &= ~0x03;\n" + " *smr |= _sci_bitrates[offset].n;\n" + " *brr = _sci_bitrates[offset].N;\n\n" + " return 0;\n" + "}\n" ); + + return 0 ; +} diff --git a/tools/cpu/sh/sci.h b/tools/cpu/sh/sci.h new file mode 100644 index 0000000000..b55bbfb670 --- /dev/null +++ b/tools/cpu/sh/sci.h @@ -0,0 +1,11 @@ +#ifndef _shgen_sci_h +#define _shgen_sci_h + +#include + +extern int shgen_gensci( + FILE *file, + double Phi /* Processor frequency [Hz] */ + ); + +#endif diff --git a/tools/cpu/sh/shgen.c b/tools/cpu/sh/shgen.c new file mode 100644 index 0000000000..57f9120e39 --- /dev/null +++ b/tools/cpu/sh/shgen.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1998,1999,2000, 2006 Ralf Corsepius, Ulm Germany. + * + * See the file COPYING for copyright notice. + */ + +#include +#include /* strcmp, strerror */ +#include /* exit */ +#include +#include + +#include "sci.h" + +static void usage( FILE* ofile, char *prog ) +{ + fprintf( ofile, "Usage: %s [options] driver\n", prog ); + fprintf( ofile, "\nOptions:\n" ); + fprintf( ofile, "Processor frequency (default 20MHz):\n") ; + fprintf( ofile, "\t-M Phi .. processor frequency [MHz]\n" ); + fprintf( ofile, "\t-K Phi .. processor frequency [KHz]\n" ); + fprintf( ofile, "\t-H Phi .. processor frequency [Hz]\n" ); + fprintf( ofile, "Driver:\n" ); + fprintf( ofile, "\tsci .. bitrate table for sci\n" ); + + fprintf( ofile, "\nWritten by Ralf Corsepius \n" ); + fprintf( ofile, "\nCopyright (c) 1998,1999,2000\tRalf Corsepius\n" ); +} + +#if HAVE_GETOPT_LONG +#define NOARG 0 +#define HASARG 1 +#define OPTARG 2 + +static struct option long_options[] = +{ + { "version", NOARG, NULL, 'v' }, + { "help", NOARG, NULL, 'h' }, + { "mega-hertz", HASARG, NULL, 'M' }, + { "kilo-hertz", HASARG, NULL, 'K' }, + { "hertz", HASARG, NULL, 'H' }, + { 0, 0, 0, 0 } +}; +#endif + +static void shgen_header( FILE *file ) +{ + fprintf( file, + "/*\n * DO NOT EDIT - this file is automatically generated by shgen %s\n", + VERSION ); + fprintf( file, + " * Copyright (c) 1998,1999,2000 Ralf Corsepius (corsepiu@faw.uni-ulm.de)\n */\n" ); + fprintf( file, + "\n/* This file is not copyrighted */\n\n" ); +} + +int main( int argc, char *argv[] ) +{ + double Phi = 20000000.0 ; + +#if HAVE_GETOPT_LONG + int option_index = 0 ; + while( ( optopt = getopt_long( argc, argv, "M:K:H:hv", + long_options, &option_index ) ) > 0 ) +#else + while ( ( optopt = getopt( argc, argv, "M:K:H:hv" ) ) > 0 ) +#endif + { + switch ( optopt ) + { + case 'M' : + sscanf( optarg, "%lf", &Phi ); + Phi = Phi * 1000000.0; + break ; + case 'K' : + sscanf( optarg, "%lf", &Phi ); + Phi = Phi * 1000.0; + break ; + case 'H' : + sscanf( optarg, "%lf", &Phi ); + break ; + case 'h' : + usage( stdout, argv[0] ); + exit(0); + case 'v' : + fprintf( stdout, "%s version %s\n", argv[0], VERSION ); + exit(0); + default : + usage( stderr, argv[0] ); + exit(1); + break ; + } + } + + if ( argc - optind != 1 ) + { + fprintf( stderr, "%s: Missing argument: driver\n", argv[0] ); + exit(1); + } + + shgen_header( stdout ); + + if ( strcmp( argv[optind], "sci" ) == 0 ) + { + shgen_gensci( stdout, Phi ); + } + else + { + fprintf( stderr, "%s: Invalid argument: driver\n", argv[0] ); + exit(1); + } + + return 0 ; +} -- cgit v1.2.3