2006-08-15 Kolja Waschk <kawk@telos.de>

* 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
This commit is contained in:
Joel Sherrill
2006-08-15 21:02:55 +00:00
parent 5f88544369
commit 16fd5a99e1
15 changed files with 1304 additions and 136 deletions

View File

@@ -1,3 +1,17 @@
2006-08-15 Kolja Waschk <kawk@telos.de>
* 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 <joel@oarcorp.com>
* nios2gen.c: Added some very basic support for --help and --version

View File

@@ -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

View File

@@ -1,17 +1,146 @@
$Id$
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.
It is structured as
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).
=================================
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

View File

@@ -29,6 +29,9 @@
now we simply assume that bridges never translate anything.
*/
#include <string.h>
#include <stdlib.h>
#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;

View File

@@ -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;

122
tools/cpu/nios2/linkcmds.c Normal file
View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}

View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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

104
tools/cpu/nios2/memory.c Normal file
View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}

29
tools/cpu/nios2/memory.h Normal file
View File

@@ -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

View File

@@ -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] <SOPC PTF> [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;
memory_desc *memory;
if (argc<2)
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();
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;
};
if ( !strcmp(argv[1], "--help") || !strcmp(argv[1],"-?") ) {
usage();
return 0;
};
if ( !strcmp(argv[1], "--version") ) {
version();
return 0;
};
cfg = ptf_parse_file(argv[1]);
if(cfg == NULL)
{
fprintf(stderr, "Couldn't parse '%s'.\n", argv[1]);
return -1;
};
printf("Successfully read config PTF file %s.\n", argv[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++;optind<argc;optind++)
{
struct ptf *morecfg = ptf_parse_file(argv[optind]);
if(morecfg == NULL)
{
fprintf(stderr, "Couldn't parse '%s'.\n", argv[optind]);
return -1;
};
if(verbose) printf("Successfully read config PTF file %s.\n", argv[optind]);
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);
}
/********************************************************/
{
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;
};
sopc = ptf_parse_file(p->value);
if(sopc == NULL)
{
fprintf(stderr, "Could not parse SOPC_PTF '%s'.\n", p->value);
return -1;
};
printf("Successfully read SOPC PTF file %s.\n", p->value);
};
/********************************************************/
/* 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");
/********************************************************/
/* Find clocks */
printf("Looking for clock definitions...\n");
clocks = find_clocks(sopc, cfg);
if(clocks)
{
clock_desc *cs;
for(cs = clocks; cs; cs = cs->next)
{
printf("Found clock: %s (%lu Hz)\n", cs->name, cs->freq);
};
}
else
{
printf("No clocks present.\n");
if(verbose)
{
printf("Using NIOS II CPU '%s'.\n", cpu->value);
printf("Only modules mastered by this CPU are considered now.\n");
};
/********************************************************/
/* Find Bridges */
printf("Looking for bus bridges...\n");
if(verbose) printf("Looking for bus bridges...\n");
bridges = find_bridges(sopc);
if(bridges)
if(verbose)
{
bus_bridge_pair *bbp;
for(bbp = bridges; bbp; bbp=bbp->next)
if(bridges)
{
printf("Found bridge: %s\n", bbp->mastered_by);
printf(" \\_%s\n", bbp->bridges_to);
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");
};
}
else
};
/********************************************************/
/* Find clocks */
if(verbose) printf("Looking for clock definitions...\n");
clocks = find_clocks(sopc, cfg);
if(verbose)
{
printf("No bridges present.\n");
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);
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");
};
};
// ptf_printf(stdout, ptf, "");
// ptf_printf(stdout, cfg, "");
/********************************************************/
/* 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;
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -9,6 +9,7 @@
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#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;
};

View File

@@ -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,

462
tools/cpu/nios2/sample.ptf Normal file
View File

@@ -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";
}