From 16fd5a99e1a8c433077e70c1a48e42cc01bf7d29 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 15 Aug 2006 21:02:55 +0000 Subject: 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 --- tools/cpu/nios2/ChangeLog | 14 ++ tools/cpu/nios2/Makefile.am | 2 + tools/cpu/nios2/README | 137 ++++++++++++- tools/cpu/nios2/bridges.c | 26 +-- tools/cpu/nios2/clocks.c | 1 - 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 | 399 ++++++++++++++++++++++++++++++-------- tools/cpu/nios2/output.c | 12 +- tools/cpu/nios2/output.h | 1 + tools/cpu/nios2/ptf.c | 62 +++++- tools/cpu/nios2/ptf.h | 2 + tools/cpu/nios2/sample.ptf | 462 ++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 1283 insertions(+), 115 deletions(-) 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/sample.ptf (limited to 'tools/cpu') diff --git a/tools/cpu/nios2/ChangeLog b/tools/cpu/nios2/ChangeLog index a59b502fb7..56f12a7198 100644 --- a/tools/cpu/nios2/ChangeLog +++ b/tools/cpu/nios2/ChangeLog @@ -1,3 +1,17 @@ +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 diff --git a/tools/cpu/nios2/Makefile.am b/tools/cpu/nios2/Makefile.am index b71477af4b..8ca3c89df0 100644 --- a/tools/cpu/nios2/Makefile.am +++ b/tools/cpu/nios2/Makefile.am @@ -11,6 +11,8 @@ nios2gen_SOURCES = nios2gen.c \ 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 diff --git a/tools/cpu/nios2/README b/tools/cpu/nios2/README index 06c59fe3fc..f961dff6b1 100644 --- a/tools/cpu/nios2/README +++ b/tools/cpu/nios2/README @@ -1,17 +1,146 @@ $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"). -It is structured as +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 -nios2gen: - Tool to generate BSP data for boards utilizing NIOS2 soft core processor. -Specify the PTF and name of the CPU (if there are more than one). diff --git a/tools/cpu/nios2/bridges.c b/tools/cpu/nios2/bridges.c index f792d5e1aa..e5f36e07c4 100644 --- a/tools/cpu/nios2/bridges.c +++ b/tools/cpu/nios2/bridges.c @@ -29,6 +29,9 @@ now we simply assume that bridges never translate anything. */ +#include +#include + #include "ptf.h" #include "bridges.h" @@ -40,24 +43,15 @@ int is_bridged( char *curr_master; bus_bridge_pair *bbp; - curr_master = dev_master; - while(curr_master != NULL) - { - /* Does cpu_master master curr_master? */ - if(strcmp(cpu_master, curr_master) == 0) return 1; /* yes, cpu_masters cm */ + if(strcmp(cpu_master, dev_master) == 0) return 1; /* cpu directly masters dev */ - /* No, cm is attached to a bridge? */ - bbp = bridges; - while(bbp != NULL) + for(bbp = bridges; bbp != NULL; bbp=bbp->next) + { + if(strcmp(cpu_master, bbp->mastered_by) == 0 && + is_bridged(bbp->bridges_to, dev_master, bridges)) { - if(strcmp(bbp->bridges_to, curr_master) == 0) - { - curr_master = bbp->mastered_by; - break; - }; - bbp = bbp->next; - }; - if(bbp == NULL) curr_master = NULL; + return 1; /* cpu masters dev via bridge */ + } }; return 0; diff --git a/tools/cpu/nios2/clocks.c b/tools/cpu/nios2/clocks.c index ac0f85cb4d..2c72770798 100644 --- a/tools/cpu/nios2/clocks.c +++ b/tools/cpu/nios2/clocks.c @@ -23,7 +23,6 @@ void add_clock_spec(struct ptf_item *pi, void *arg) if(new_clock == NULL) return; new_clock->freq = strtoul(pi->item[pi->level]->value, 0, 0); - printf("freq = %lu (%s?)\n", new_clock->freq, pi->item[pi->level]->value); new_clock->cfgname = NULL; new_clock->name = pi->item[pi->level-1]->value; diff --git a/tools/cpu/nios2/linkcmds.c b/tools/cpu/nios2/linkcmds.c new file mode 100644 index 0000000000..46e0c05755 --- /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..0c35953354 --- /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 index fb271735ca..a62f0e3120 100644 --- a/tools/cpu/nios2/nios2gen.c +++ b/tools/cpu/nios2/nios2gen.c @@ -16,7 +16,14 @@ #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" /********************************************************/ @@ -64,29 +71,39 @@ void read_include_file(struct ptf_item *pi, void *arg) p->next = next; } -void usage() -{ -printf( - "Usage: nios2gen [PTFFILE]\n" - "Generate BSP data based upon PTF file from SOPC Builder.\n" - "\n" - "Please specify the name of a nios2gen PTF file that describes where to\n" - "find the system description PTF from SOPC Builder on the command line.\n" -); -} +/********************************************************/ -void version() +void version(FILE *f) { -printf( - "RTEMS/NIOS nios2gen\n" +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[]) @@ -96,69 +113,157 @@ int main(int argc, char *argv[]) device_desc *devices; bus_bridge_pair *bridges; clock_desc *clocks; - - if (argc<2) + 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(); - return -1; + usage(stderr,"Too many commandline arguments!\n"); + return -1; }; - if ( !strcmp(argv[1], "--help") || !strcmp(argv[1],"-?") ) { - usage(); + 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; - }; - if ( !strcmp(argv[1], "--version") ) { - version(); + 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); + }; }; - cfg = ptf_parse_file(argv[1]); - if(cfg == NULL) + if(optind >= argc) { - fprintf(stderr, "Couldn't parse '%s'.\n", argv[1]); + usage(stderr,"No PTF specified!\n"); return -1; }; - printf("Successfully read config PTF file %s.\n", argv[1]); - /********************************************************/ + sopc = ptf_parse_file(argv[optind]); + if(sopc == NULL) { - struct ptf include_item = { item, "INCLUDE", 0, 0, 0 }; - struct ptf_item inc_file_spec = { 1, &include_item }; - ptf_match(cfg, &inc_file_spec, read_include_file, 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]); /********************************************************/ - - { - struct ptf *p; - struct ptf sopc_ptf_item = { item, "SOPC_PTF", 0, 0, 0 }; - struct ptf_item sopc_ptf_spec = { 1, &sopc_ptf_item }; - ptf_match(cfg, &sopc_ptf_spec, store_ptf_ptr, &p); - if(p == NULL) - { - fprintf(stderr, "Missing 'SOPC_PTF' filename in %s!\n", argv[1]); - return -1; - }; + cfg = NULL; - sopc = ptf_parse_file(p->value); - if(sopc == NULL) + for(optind++;optindvalue); - return -1; + fprintf(stderr, "Couldn't parse '%s'.\n", argv[optind]); + return -1; }; + + if(verbose) printf("Successfully read config PTF file %s.\n", argv[optind]); - printf("Successfully read SOPC PTF file %s.\n", p->value); + cfg = ptf_concat(cfg, morecfg); }; + /********************************************************/ + /* Pull in include files specified in the configs; */ + /* Only one level is read; included files are not */ + /* checked for further INCLUDEs */ + + { + struct ptf include_item = { item, "INCLUDE", 0, 0, 0 }; + struct ptf_item inc_file_spec = { 1, &include_item }; + ptf_match(cfg, &inc_file_spec, read_include_file, NULL); + } + /********************************************************/ /* Find CPU */ - printf("Looking for usable CPUs...\n"); + if(verbose) printf("Looking for usable CPUs...\n"); + /* Check if a CPU has been specified in the config PTF */ { struct ptf modules = { section, "MODULES", 0, 0, 0 }; struct ptf cpu_def = { item, "CPU", 0, 0, 0 }; @@ -167,6 +272,7 @@ int main(int argc, char *argv[]) ptf_match(cfg, &cpu_spec, store_ptf_ptr, &cpu); }; + /* Look for CPUs in system description PTF */ { int cpu_count; struct ptf system = { section, "SYSTEM", 0, 0, 0 }; @@ -180,73 +286,206 @@ int main(int argc, char *argv[]) if(cpu_count > 1) { - printf("There is more than one CPU. Please specify the one\n"); - printf("you want to use with this BSP in your config file.\n"); - printf("The available CPUs are named as follows:\n"); + 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) { - printf("There is no NIOS2 cpu in the system.\n"); + fprintf(stderr, "There is no NIOS2 cpu in the system.\n"); return -1; } }; - printf("Using NIOS II CPU '%s'.\n", cpu->value); - printf("Only modules mastered by this CPU are considered now.\n"); + if(verbose) + { + printf("Using NIOS II CPU '%s'.\n", cpu->value); + printf("Only modules mastered by this CPU are considered now.\n"); + }; /********************************************************/ - /* Find clocks */ + /* Find Bridges */ - printf("Looking for clock definitions...\n"); + if(verbose) printf("Looking for bus bridges...\n"); - clocks = find_clocks(sopc, cfg); + bridges = find_bridges(sopc); - if(clocks) + if(verbose) { - clock_desc *cs; - for(cs = clocks; cs; cs = cs->next) + 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("Found clock: %s (%lu Hz)\n", cs->name, cs->freq); + printf("No bridges present.\n"); }; - } - else - { - printf("No clocks present.\n"); }; /********************************************************/ - /* Find Bridges */ + /* Find clocks */ - printf("Looking for bus bridges...\n"); + if(verbose) printf("Looking for clock definitions...\n"); - bridges = find_bridges(sopc); + clocks = find_clocks(sopc, cfg); - if(bridges) + if(verbose) { - bus_bridge_pair *bbp; - for(bbp = bridges; bbp; bbp=bbp->next) + 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("Found bridge: %s\n", bbp->mastered_by); - printf(" \\_%s\n", bbp->bridges_to); + printf("No clocks present.\n"); }; - } - else - { - printf("No bridges present.\n"); }; /********************************************************/ /* Find other devices available to the selected CPU */ + if(verbose) printf("Looking for devices...\n"); + devices = find_devices(sopc, cfg, cpu, bridges); - fwrite_header_file(stdout, cfg, devices, clocks); + 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); + } + } + }; + } + }; - // ptf_printf(stdout, ptf, ""); - // ptf_printf(stdout, cfg, ""); + if(verbose) printf("Done.\n"); return 0; } diff --git a/tools/cpu/nios2/output.c b/tools/cpu/nios2/output.c index e957e430a7..d9f368d05c 100644 --- a/tools/cpu/nios2/output.c +++ b/tools/cpu/nios2/output.c @@ -150,11 +150,12 @@ void fwrite_header_file( FILE *file, struct ptf *cfg, device_desc *devices, cloc struct ptf aclass = { section, "CLASS", 0, 0, 0 }; struct ptf_item matchaclass = { 1, &aclass }; - struct ptf header = { item, "HEADER", 0, 0, 0 }; - struct ptf_item matchheader = { 1, &header }; + 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 = { 1, &epilog }; + struct ptf_item matchepilog = { 2, &bspsect, &epilog }; out_desc dinfo; @@ -162,7 +163,7 @@ void fwrite_header_file( FILE *file, struct ptf *cfg, device_desc *devices, cloc dinfo.clocks = clocks; dinfo.devices = devices; - ptf_match(cfg, &matchheader, fwrite_value, file); + ptf_match(cfg, &matchleadtext, fwrite_value, file); if(clocks) { @@ -177,7 +178,7 @@ void fwrite_header_file( FILE *file, struct ptf *cfg, device_desc *devices, cloc { for(dinfo.dev = devices; dinfo.dev; dinfo.dev=dinfo.dev->next) { - fprintf(file, "\n"); + /* fprintf(file, "\n#define SOPC_HAS_%s 1\n", dinfo.dev->cfgname); */ p = ptf_find(dinfo.dev->ptf, &pi, item, "class", 0); if(p) @@ -191,5 +192,4 @@ void fwrite_header_file( FILE *file, struct ptf *cfg, device_desc *devices, cloc ptf_match(cfg, &matchepilog, fwrite_value, file); } - diff --git a/tools/cpu/nios2/output.h b/tools/cpu/nios2/output.h index 32aa0f7940..ad36629bf8 100644 --- a/tools/cpu/nios2/output.h +++ b/tools/cpu/nios2/output.h @@ -19,6 +19,7 @@ #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 index 43a38ea522..6f8943d0b3 100644 --- a/tools/cpu/nios2/ptf.c +++ b/tools/cpu/nios2/ptf.c @@ -9,6 +9,7 @@ */ #include +#include #include #include "ptf.h" @@ -364,7 +365,7 @@ void parse_char(struct ptf_parser_state *state, int c) default: #if DEBUG&DEBUG_EXPECTATIONS - printf("Expectation: %d (???)\n", state->expectation); + printf("Expectation: %d (?)\n", state->expectation); #endif parse_error(state, "Internal error: Unhandled state of expectation"); @@ -510,6 +511,44 @@ struct ptf *ptf_parse_file(char *filename) /***************************************************************************/ +struct ptf *ptf_concat(struct ptf *a, struct ptf *b) +{ + struct ptf *leaf = a; + + if(!a) return b; + if(!b) return a; + + for(leaf = a; leaf->next != 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; @@ -532,12 +571,12 @@ void ptf_printf(FILE *s, struct ptf *tree, char *prefix) strcat(new_prefix, leaf->name); if(leaf->value != NULL && leaf->value[0] != 0) { - strcat(new_prefix, "_"); + strcat(new_prefix, ":"); strcat(new_prefix, leaf->value); }; strcat(new_prefix, "/"); fputs(new_prefix, s); - fputs("\r\n", s); + fputs("\n", s); ptf_printf(s, leaf->sub, new_prefix); break; }; @@ -548,12 +587,19 @@ void ptf_printf(FILE *s, struct ptf *tree, char *prefix) fputs(prefix, s); fputs(leaf->name, s); fputs(" = \"", s); - for(c=leaf->value; *c; c++) + if(leaf->value == NULL) { - if(*c=='\\' || *c=='"') putc('\\', s); - putc(*c, s); - }; - fprintf(s, "\"\r\n"); + fputs("(NULL)", s); + } + else + { + for(c=leaf->value; *c; c++) + { + if(*c=='\\' || *c=='"') putc('\\', s); + putc(*c, s); + }; + } + fprintf(s, "\"\n"); break; }; diff --git a/tools/cpu/nios2/ptf.h b/tools/cpu/nios2/ptf.h index 50955cb4a5..3683b98163 100644 --- a/tools/cpu/nios2/ptf.h +++ b/tools/cpu/nios2/ptf.h @@ -40,8 +40,10 @@ struct ptf_item 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, 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"; +} + -- cgit v1.2.3