This appendix contains the following sections:
Introduction
Getting Started
Introduction
Basic Structure
CPU Part
Introduction
Address Translation: map and mem
Address Spaces
Addressing Modes
Busses
Chips
External Memory
Software Part
Introduction
Load Module
Layout Description
Space Definition
Block Definition
Selecting Sections
Cluster Definition
Amode Definition
Manipulating Sections in Amodes
Section Placing Algorithm
Delfee Preprocessing
Introduction
User Defined Macros
File Inclusion
Conditional Statements
Delfee Keyword Reference
Abbreviation of Delfee Keywords
Delfee Keywords Summary
In an embedded environment an accurate description of available memory and control over the behavior of the locator is crucial for a successful application. For example, it may be necessary to port applications to processors with different memory configurations, or it may be necessary to tune the location of sections to take full advantage of fast memory chips.
For this purpose the DELFEE language, which stands for DEscriptive Language For Embedded Environments, was designed.
This section gives a general introduction about the DELFEE description language. The goal is to give you an overview and some basic knowledge what the DELFEE description language is about, and how a basic description file looks. A more detailed description and examples are given in the following sections.
The DELFEE language describes where code or data sections should be placed on the actual memory chips. This language has to define the interface between a virtual world (the software) and a physical world (the hardware configuration).
On the one side, in the virtual world, there are the code and data sections which are described by the assembly language. Sections can have names, attributes like writable or read-only and can have an address in the addressing space or an addressing mode describing the range of the address space in which they may be located.
On the other side, the physical world, the actual processor is present which reads instructions from memory chips and interprets these instructions. With the DELFEE language you can instruct the locator to place the code and data sections at the correct addresses, taking into account things like the type of memory chip (rom/ram, fast/slow), availability of memory, etc. The DELFEE language gives the possibility to tune the same application for different hardware configurations.
In the DELFEE language the interface between virtual and physical world is described in three parts:
1. software part (*.dsc)
The software part belongs to the virtual world and describes the order in which data and code sections should be located. The software part may vary for different applications and can even be empty.
2. cpu part (*.cpu)
The cpu part is the interface between the virtual world and the real world. It contains the application independent part of the virtual world (the address translation of addressing modes to the addressing space), and the configuration independent part of the physical world (on-chip memory, address busses). The cpu part is independent of application and configuration.
3. memory part (*.mem)
The memory belongs to the physical world. It contains the description of the external memory. The memory part may vary for different configurations and can even be empty (if there is no external memory).
The software part and the memory part can be empty, but
the cpu part must always be defined.
The DELFEE language is used in a special file, which is called the description file. In the DELFEE description language the different parts are defined with the following syntax:
software { layout { // ordering of sections } } cpu { // mapping of addressing modes to address space // defining address space // mapping of address space to actual busses // defining on-chip memory } memory { // description of external memory }
You can use C++ style comments. Everything after '//' until the end of line is ignored.
For convenience the cpu part and the memory part can be placed in different files, which makes it possible to have different layout parts for different applications and different memory parts for different configurations. The files can be included using the syntax:
cpu filename // include cpu part defined in file filename mem filename // include memory part defined in file filename
The cpu part contains the application and configuration independent part of the description file. This part defines the translations of the addresses from the assembler language (virtual addresses) all the way down to the chips (physical addresses). To describe the translations, DELFEE recognizes four main levels:
1. addressing mode(s) definitions. Addressing modes are subsets of an address space. They define address ranges within an address space.
2. address space(s) definitions. The address space is the total range of addresses available.
3. bus(ses) definitions.
4. (on-chip) memory chips definitions.
The address translation is defined from addressing mode via space and bus to the chip. The addressing modes and the busses can be nested, the space and the chip cannot.
Figure G-1: Address translation
The addressing modes and addressing spaces belong to the virtual part, the busses and chips belong to the physical part. The following sections describe the address space and the addressing modes which are subsets of the address space. Then a description of the physical side (hardware configuration) follows, describing the busses and chips that are available.
The following example illustrates what a cpu part could look like. It is a fictitious example, mainly used to illustrate the definitions. You should be able to recognize the addressing mode definitions, address space definition, bus definitions and on-chip memory definition. Each definition is explained in the following sub-sections.
cpu { // // addressing mode definitions // amode near_code { attribute Y1; mau 8; map src=0 size=1k dst=0 amode = far_code; } amode far_code { attribute Y2; mau 8; map src=0 size=32k dst=0 space = address_space; } amode near_data { attribute Y3; mau 8; map src=0 size=1k dst=0 amode = far_data; } amode far_data { attribute Y4; mau 8; map src=0 size=32k dst=32k space = address_space; }
// // space definitions // space address_space { mau 8; map src=0 size=32k dst=0 bus = address_bus label = rom; map src=32k size=32k dst=32k bus = address_bus label = ram; }
// // bus definitions // bus address_bus { mau 8; mem addr=0 chips=rom_chip; map src=0x100 size=0x7f00 dst=0x100 bus = external_rom_bus; mem addr=32k chips=ram_chip; map src=0x8100 size=0x7f00 dst=0x100 bus = external_ram_bus; } // // internal memory definitions // chips rom_chip attr=r mau=8 size=0x100; // internal rom chips ram_chip attr=w mau=8 size=0x100; // internal ram }
In DELFEE there are two ways to describe a memory translation between two levels (the source level and the destination level):
1. map keyword. This is for address translations between amodes, spaces, busses (not chips).
2. mem keyword. This describes the address translation between bus and chip. mem is a simplified case of map.
Figure G-2: Map address translation
The generalized syntax for the map definition is (see figure G-2):
where,
src start address of the source level. In case of an address translation between amodes and spaces, the source level is the amode and the destination level is the space.
size length of the source level.
dst start address at the destination level.
destination_type the destination type depends on the context the mapping is used in and can have three different types:
1. amode allowed in context: amode.
2. space allowed in context: amode.
3. bus allowed in context: space, bus.
optional_specifiers The optional identifiers are also dependent of the context they are used in:
1. label Only allowed in space context and needed as a reference for the block definition in the software part (see section 4.5).
label = name ;
2. align This indicates that every section will be aligned at the specified value.
align = number ;
3. page This indicates that every section should be within a given page size.
page = number ;
Both the source level and the destination level have an address range that is expressed in a number of Minimum Addressable Units (MAU, the minimal amount of storage, in bits, that is accessed using an address). The mapping only describes the range and the destination of the address mapping, the actual transformation also depends on the memory unit that an address can access. If a source level with a minimum addressable unit of 8 bits (mau=8) maps to a destination level with a minimum addressable unit of 16 bits (mau=16), the size of the destination level, expressed in address range, is half the original size. So, according to figure G-2, the size of the destination level is 100.
If a map is present from level1 down to level2, the map definition works as follows:
end_address of level2 = dst + ( size * mau of level1 / mau of level2 )
The mem description is actually a simplified case of the map description. The length of the address translation is taken from the chip size, the destination address is always zero. It is used to map a bus to a chip.
The syntax is:
where,
addr start address location of a chip.
chips the name of the chip that is located at address number.
The link between the virtual and the physical world is the description of the address space and the way it maps onto the internal address busses.
The address space is defined by the complete range of addresses that the instruction set can access. Some instruction sets support multiple address spaces (for example a data space and a code space).
An address space is described by the syntax:
where,
space defines the name by which the space can be referenced in the description file.
mau the Minimum Addressable Unit, meaning the minimum amount of storage (in bits) that is accessed using an address.
map this specifies the mapping of a range of addresses in the address space to a bus defined by bus_name. The range of addresses is defined by src and size, the offset on the bus is defined by dst. (The bus you map the address space on, may have a different MAU, which will lead to another length of the range of the bus). An address space can only map onto a bus.
Usually an address in the address space corresponds to the same address on the bus. In that case src and dst have the same value.
In the previous example there is one space definition:
space address_space { mau 8; map src=0 size=32k dst=0 bus = address_bus label = rom; map src=32k size=32k dst=32k bus = address_bus label = ram; }
In this example the space is named address_space. Note that the amode definitions use this name as destination for their mappings. The minimum addressable unit (MAU) is set to 8 bits. The labels rom and ram are used by block definitions in the software part which are discussed in section 4.5.
Addressing modes define address ranges in the addressing space. Addressing modes usually have a special characteristic, like bitaddressable part of memory, parts especially for code sections, zero pages, etc. The addressing modes are defined by the instruction set. The syntax of defining an addressing mode in the DELFEE language is:
An address space is described by the syntax:
where,
amode The name by which the addressing mode can be referenced. In the object file the addressing mode of a section is encoded with an Ynumber. This means that the name given to the addressing mode has only meaning within the description file, not to the sections!
mau the Minimum Addressable Unit, meaning the minimum amount of storage (in bits) that is accessed using an address.
attr Y the addressing mode number. Code or data sections (generated by the assembler) all have a number specifying the addressing mode they belong to. In the DELFEE description file this number is used to identify the addressing mode. This number must never be changed, because the interpretation of the sections will get mixed up.
map defines the mapping of the addressing mode to another addressing mode (amode) or an address space (space).
Below is an example of two addressing mode definitions:
amode near_data { attribute Y3; mau 8; map src=0 size=1k dst=0 amode = far_data; } amode far_data { attribute Y4; mau 8; map src=0 size=32k dst=32k space = address_space; }
Figure G-3: Addressing mode mapping
In this example the addressing modes are named near_data and far_data. They are identified by the addressing mode numbers Y3 and Y4 respectively. The minimum addressable unit (MAU) is set to 8 bits. Addressing mode near_data maps on addressing mode far_data, and far_data, in its turn, maps on address space address_space. address_space is the space as discussed in the previous section.
The bus keyword describes the bus configuration of a cpu. In essence it describes the address translation from the address space to the chip. The syntax is:
where,
bus the name by which the bus can be referenced.
mau the Minimum Addressable Unit, meaning the minimum amount of storage (in bits) that is accessed using an address.
map mapping to another bus.
mem mapping to a memory chip.
Below is an example of a bus definition:
bus address_bus { mau 8; mem addr=0 chips=rom_chip; map src=0x100 size=0x7f00 dst=0x100 bus = external_rom_bus; mem addr=32k chips=ram_chip; map src=0x8100 size=0x7f00 dst=0x100 bus = external_ram_bus; }
Figure G-4: Bus mapping
In this example the address bus is named address_bus. The minimum addressable unit (MAU) is set to 8 bits. The internal memory chip rom_chip is located at address 0 of the bus, and the chip ram_chip is located at address 32k.
Two address mappings to other busses are present: one to external_rom_bus and one to external_ram_bus.
The first mapping translates addresses 0x100-0x7ff of address_bus (src=0x100 size=0x7f00) onto addresses of external_rom_bus starting at address 0x100 (dst=0x100).
The second mapping translates addresses 0x8100-0xffff of address_bus (src=0x8100 size=0x7f00) onto addresses of external_ram_bus starting at address 0x100 (dst=0x100).
The second mapping maps to RAM, not ROM. That is why
both destination addresses are the same.
The chips keyword describes the memory chip. The syntax is:
where,
chips the name by which the chip can be referenced.
attr defines the attributes of the chip with a letter code
letter_code one of the following attributes:
r read-only memory.
w writable memory.
s special memory (it must not be located).
mau the Minimum Addressable Unit, meaning the minimum amount of storage (in bits) that is accessed using an address.
size the size of the chip (address range from 0-size).
Below is an example of two chip definitions:
chips rom_chip attr=r mau=8 size=0x100; // internal rom chips ram_chip attr=w mau=8 size=0x100; // internal ram
In this example the chips are named rom_chip and ram_chip. The minimum addressable unit (MAU) is set to 8 bits. The size of both chips is 0x100 MAUs (= 256 bytes). Chip rom_chip is read-only and chip ram_chip writable, as you would expect with ROM and RAM.
With the syntax described in the previous sections it would be possible to define mappings from an address space to external memory chips (DELFEE does not actually know, or care, if memory is on-chip). However, this is not advisory. For maintenance and flexibility reasons it is better to keep the internal (static) memory part apart from the external (variable) memory part. The chapter Memory Part describes how to deal with external memory.
In the cpu part you only have to define a mapping to an external bus, which can later be defined in the memory part. The following example contains references to two external busses: external_ram_bus and external_rom_bus.
bus address_bus { mau 8; mem addr=0 chips=rom_chip; map src=0x100 size=0x7f00 dst=0x100 bus = external_rom_bus; mem addr=32k chips=ram_chip; map src=0x8100 size=0x7f00 dst=0x100 bus = external_ram_bus; }
The software part has two main parts:
1. load_mod
2. layout description
software { load_mod start = start_label; layout { // ordering of sections } }
The keyword load_mod defines the program start label. The program start label is the start of the code and the reset vector should point to this label. The locator generates a warning if this label is not referenced.
load_mod start = start_label;
First of all, the layout definition can be omitted. If you omit the layout definition, the locator will generate a layout definition based on the DELFEE description of the amodes (addressing modes) in the cpu part (See section 3). However this does not allow you to control the order in which sections (like stack and heap) are located. If you define the layout part, the locator uses this description.
The layout part is probably the most difficult part of the DELFEE language. It is designed to give the locate algorithm the information it needs to locate the sections correctly. Through some examples you will be shown how to control the locating process using the DELFEE language.
To give you an idea of where all this will lead to, an example of a layout part is given:
layout { space address_space { block rom { cluster first_code_clstr { attribute i; amode near_code; amode far_code; } cluster code_clstr { attribute r; amode near_code { section selection=x; section selection=r; } amode far_code { table; section selection=x; section selection=r; copy; // locate rom copies here } } } block ram { cluster data_clstr { attribute w; amode near_data { section selection=w; } amode far_data { section selection=w; heap; stack; } } } } }
The layout definition is defined with the syntax:
The first thing to notice is the different levels inside the layout definition:
space This level can only occur inside a layout level. There are as many space levels as there are space definitions in the cpu part.
block This level can only occur inside a space level. There are as many block levels as there are mappings defined in the space definition in the cpu part.
cluster This level can only occur inside a block level. There can be multiple clusters inside a block. Their main purpose is to group (code/data) sections. The locator locates each cluster in the specified order.
amode This level can only occur inside a cluster level. An amode corresponds to an amode definition in the cpu part. Within an amode you can specify the order in which data/code sections are located.
The four levels can roughly be divided in two groups. The space and block definition correspond to address ranges and the cluster and amode definition correspond to (groups of) sections.
The following paragraphs first introduce the space and block definition. Then separate paragraphs show how to select certain groups of sections and how this is used in the cluster and amode definition.
Section 3.3 already defined the address translation of a space in the cpu part. In the example in that section, the following space was defined:
space address_space { mau 8; map src=0 size=32k dst=0 bus = address_bus label = rom; map src=32k size=32k dst=32k bus = address_bus label = ram; }
For every space defined in the cpu part you have to provide a description in the layout definition.
The space level should be inside the layout definition and can only contain one or more block levels.
The name of the space must correspond to a space definition in the cpu part.
The syntax is:
Below is an example of a space definition from the software part:
space address_space { block rom { .... } block ram { ... } }
In this example space address_space defines two blocks: block rom and block ram.
With the block description you can set boundaries to the sections based on chip sizes.
A block references a physical area of memory. Selected sections are only allowed within the range of the block description. In effect a block limits the range in which a section can be located.
The physical address range of a block is actually defined in the cpu part by a labeled mapping:
space address_space { mau 8; map src=0 size=32k dst=0 bus = address_bus label = rom; //<-- // --> block name: rom map src=32k size=32k dst=32k bus = address_bus label = ram; //<-- // --> block name: ram }
The name of the block description must correspond to a label in the map definition of a space definition in the cpu part. The block definition must be inside the space definition and can only contain one or more cluster levels.
The syntax is:
Below is an example of a bus definition from the software part:
block rom { cluster first_code_clstr { ... } cluster code_clstr { ... } }
In this example block rom defines two clusters: cluster first_code_clstr and cluster code_clstr.
The previous paragraphs explained how the address ranges are defined by block definitions, now it is time to select the sections that should be placed in these blocks. In DELFEE there are two levels in which you can define the order of locating:
1. cluster
2. amode
To define the locating order you need to have some kind of handle to specify a section or a group of sections. DELFEE recognizes the following characteristics of a section:
name of the section This is unique to a specific section.
attribute(s) of a section
The attributes of a section are specified
by the assembler or compiler. Possible attributes are defined in table G-1. By selecting
an attribute you select a group of sections. The attributes can be grouped to an attribute string, for example: by1w.
addressing mode All sections have an addressing mode (as defined in the cpu part).
attr | Meaning | Description | ||||||||||||||||||
W | Writable | Must be located in ram | ||||||||||||||||||
R | Read only | Can be located in rom | ||||||||||||||||||
X | Execute only | Can be located in rom | ||||||||||||||||||
Ynum | Addressing mode |
Must be located in addressing mode num
A |
Absolute |
Already located by the assembler |
B |
Blank |
Section must be initialized to '0' (cleared) |
F |
Not filled |
Section is not filled or cleared (scratch) |
I |
Initialize |
Section must be initialized in rom |
N |
Now |
Section is located before normal sections (without N or P) |
P |
Postponed |
Section is located after normal sections (without N or P) | |
Table G-1: Section Attributes
To specify a (group) of sections, DELFEE has the following syntax:
1. select a group on section attribute:
2. select a section by name:
3. select a special section:
4. create a section:
Instead of selecting a section by an attribute, DELFEE also allows excluding a section by its attribute.
Excluding an attribute is done by placing a '-' (minus sign) in front of attr.
So, the example:
section selection=attr1-attr2
selects a group of sections with attribute attr1 and without attribute attr2.
Clusters are used to place specified sections in a group. The locator will handle the clusters in the order that they are specified. This gives you the possibility to create a group of selected sections and give it a higher locate priority.
There are several possibilities to specify that a section is part of a cluster. The exact rules and their priorities are given in the paragraph Section Placing Algorithm. The three main possibilities are:
1. attribute
2. section selection=
3. amode definition
Examine the following example:
layout { space address_space { block rom { cluster first_code_clstr { attribute i; amode near_code; amode far_code; } cluster code_clstr { attribute r; amode near_code { section selection=x; section selection=r; } amode far_code { table; section selection=x; section selection=r; copy; // locate rom copies here } } } } }
In this example an extra cluster first_code_cluster was created. Using the placing algorithm (paragraph 4.10) you can see that sections with attribute 'i' will be placed in cluster first_code_clstr and therefore will get a higher priority than sections in cluster code_clstr.
The syntax is:
Within a cluster the sections with the least freedom are located first. Freedom is defined by the possible addresses a section can be located at.
Within a cluster you can specify an addressing mode or amode. Although in the cpu part (paragraph 3.4) an address range was assigned to every amode, in the layout part the addressing mode is used to identify groups of sections.
The syntax is:
The order of locating is now determined by the order of specification.
For example, suppose you want to locate all writable sections first, then the heap, followed by the stack. In the DELFEE language this is specified by:
: section selection = w; // 'w' means writable sections heap; stack; :
The previous paragraphs explained how to set the order of the sections within an amode definition. DELFEE recognizes an extra set of keywords to further tune the locating of code and data sections.
An amode definition can contain the following keywords:
Keyword | Description |
section | Selects a section, or group of sections |
selection | Specifies attributes for grouping sections |
attribute | Assigns attributes (are past to the cluster |
copy | Selects a rom copy of a section by name, or all rom copies in general |
fixed | Forces a section to be located around a fixed address |
gap | Creates a gap in the address range where sections will not be located |
reserved | Reserves a memory area, which can be referenced using locator labels |
heap | Defines the place and attributes of the heap |
stack | Defines the place and attributes of the stack |
table | Defines the place and attributes of the copy table |
assert | A user defined assertion |
length | Specifies the length of stack, heap, physical block or reserved space |
Table G-2: amode keywords
All keywords are described in section 7, Delfee Keyword Reference.
There are different ways to reference a section. Sections can be referenced as a group based on a certain attribute, or they can be referenced very specific by name. To find out where sections are placed in the layout part, DELFEE uses the following algorithm:
1. First, try to find a selection by section name.
2. If not found, search for a 'section selection=' within a matching amode block.
3. If not found, search for a 'section selection=' not within an amode block.
4. If not found, search for a cluster with a correct 'amode= ..,..,.. ;' and correct attributes.
5. If not found, search for a cluster with correct attributes.
6. If not found, relax attribute checking, and start over again.
Relax attributes using the following rules:
1. If stack, heap or reserved, switch indication off and try again.
2. If attribute 'f' (not filled), switch 'f' off and try again.
3. If attribute 'b' (clear), switch 'b' off and try again.
4. If attribute 'i' (initialize), switch 'i' off and try again.
5. If attribute 'x' (executable code), switch 'x' off and 'r' (read-only) on and try again. (Try to place executable sections in read-only memory).
6. If attribute 'r' (read-only), switch 'r' off 'w' (writable) on and try again. (Try to place read-only sections in writable memory).
The memory part defines the variable part of the memory configuration. It can be placed in a different file, which allows to easily switch between different memory configurations. The syntax used for the mappings is the same as used in the cpu part.
As you have seen in the example of the cpu part in section 3, there were two references to external busses:
bus address_bus { mau 8; mem addr=0 chips=rom_chip; map src=0x100 size=0x7f00 dst=0x100 bus = external_rom_bus; mem addr=32k chips=ram_chip; map src=0x8100 size=0x7f00 dst=0x100 bus = external_ram_bus; }
In the memory part you have to define the description for the busses external_rom_bus and external_ram_bus. Using the description in sections 3.5 and 3.6 for specifying busses and chips, the memory part could look like:
memory { bus external_rom_bus { mau 8; mem addr=0 chips=xrom; } chips xrom attr=r mau =8 size=0x8000; bus external_ram_bus { mau 8; mem addr=0 chips=xram; } chips xram attr=w mau=8 size=0x8000; }
You can preprocess a DELFEE description file using exactly the same syntax as used by the C preprocessor. This means that all preprocessor directives start with a '#'-sign.
The preprocessor scans the input (description) file looking for macro calls. A macro-call is a request to the preprocessor to replace the call pattern of a built-in or user-defined macro with its definition.
There are two types of macro definitions: 'plain' macros and 'function-like' macros. A plain macro is expanded to a fixed string of characters. A function-like macro looks like a function call. The macro is expanded to its definition, in which the macro parameters are replaced by their co corresponding macro arguments.
You can create macros with the #define preprocessor directive.
When you create a parameterless macro, there are two parts to a #define call: the macro-name and the macro-body. The macro-name defines the name used when the macro is called; the macro-body defines the return value of the call.
The macro-body is usually the return value of the macro call. However, the macro-body may contain calls to other macros. If so, the return value is actually the fully expanded macro-body, including the return values of the call to other macros.
#define ASIZE 10
Every occurrence of ASIZE is expanded to '10'.
If the only function of the macro processor was to perform simple string replacement, then it would not be very useful for the most programming tasks. Each time you want to change even the simplest part of the macro's return value you would have to redefine the macro. Parameters in macro calls allow more general-purpose macros. Parameters leave holes in a macro-body that are filled in when you call the macro. This permits you to design a single macro that produces code for typical operations. The term 'parameters' refers to both the formal parameters that are specified when the macro is defined (the holes), and the actual parameters or argument that are specified when the macro is called (the fill-ins). To define macros with parameters you have to add a formal-parameter-list. The formal-parameter-list is a list of macro identifiers separated by ','. These identifiers comprise the formal parameters used in the macro. The macro identifier for each parameter in the list must be unique.
After
#define ADD(a, b) a + b
the call ADD(4, 5) is expanded to 4 + 5.
You can undefine a preprocessor macro with the #undef preprocessor directive:
With the #include preprocessor directive:
you can include text from include-file within the input text of the description file. At the occurrence of an #include control line, the preprocessor reads the text from include-file until end-of-file is reached. #include files may be nested. include-file is any file that contains description file information. include-file is searched for in the directory etc directory relative to the installation path of your product.
The ANSI standard defines the following terms for the include directive:
The preprocessor uses the following search rules for include files between " ":
1. search in the directory of the description file
2. search in the directory etc relative to the installation path of your product
Note that if you nest include files, the preprocessor applies the first rule for each level.
product.dsc: #include "../inc/product.cpu" product.cpu: #include "prod2.cpu"
According to rule 1 the preprocessor searches prod2.cpu in the same directory as product.cpu since prod2.cpu is included by product.cpu and not by product.dsc.
The preprocessor searches for include files between < > in the same way as for include files between " ". The difference is that rule 1 does not apply (the directory of the source description file is not searched).
The third form of include directives:
means that the included file name may be a token sequence that has been defined before. After expansion by the preprocessor this should produce a valid include directive as described by the first two forms:
#ifdef STD #define cpu_incl <product.cpu> #else #define cpu_incl "my_cpu.cpu" #endif #include cpu_incl
Some preprocessor directives expect logical expressions in their arguments. Logical expressions follow the same rules as numeric expressions. The difference is in how preprocessor interprets the value that the expression represents. Once the expression has been evaluated to a value, the preprocessor uses the '= 0' comparison to determine whether the expression is TRUE or FALSE (if the value is equal 0 the expression is FALSE else TRUE).
The #if and #elif preprocessor directives evaluate a logical expression, and based on that expression, expand or withhold their statements. The #ifdef and #ifndef preprocessor directives evaluates the existence of a user-defined macro, and based on the result, expand or withhold their statements.
where if-line is one of:
The expression in the #if directive and subsequent #elif directives are evaluated in order until a TRUE value is encountered. If the value is TRUE, then the preprocessor expands the succeeding statements; if the value is FALSE and the optional #else directive is included in the call, then the statements succeeding #else are expanded. If the expression results to FALSE and the #else is not included, the #if call returns the null string.
The #ifdef tests if the macro-name is a previously defined macro. The #ifndef evaluates its statements if the macro-name is not currently defined.
Each #if, #ifdef and #ifndef directive must have a corresponding #endif.
#define _STCK 100 #if _STCK == 100 stack length=100; #else stack length=200; #endif
This example always expands to: stack length=100;. In this case the #if control line could also be written as:
#ifdef _STCK
This section contains an alphabetical description of all keywords that can be used in a description file. Some keywords can be abbreviated to a minimum of four characters. Everything after '//' until the end of line is considered a comment.
.addr (Software part)
The predefined label .addr contains the current address.
block ram { cluster data_clstr { attribute w; amode near_data { section selection=w; assert ( .addr < 256, "page overflow"); // if the condition is false, // the locator generates an error with // the text as message } ... } }
address = address (all parts)
addr = address (abbreviated form)
Specify an absolute address in memory.
Cpu or memory part:
bus address_bus { mau 8; mem addr=0 chips=rom_chip; ... mem addr=32k chips=ram_chip; ... }
Software part:
block rom { ... cluster code_clstr { attribute r; amode near_code { section selection=x; section selection=r; section .string address = 0x0100; } ... } }
The locate order in the amode definition
in the example above is fixed. Sections with attribute selection 'x' and/or 'r' are forced
to be located before section .string. If this fixed order is not desired, the absolute address specification can be done in a separate amode definition.
amode near_code { section .string address = 0x0100; } amode near_code { section selection=x; section selection=r; }
align = power_of_2 (Software part)
Specify the alignment of a section. The alignment should be a power of 2 (even addresses).
In the following example section DATA will be aligned on 2 MAUs:
... amode near_data { section DATA align = 2; } ...
(Cpu or memory part)
amode identifier[, identifier]...
{ amod_description } (def)
amode = identifier (ref)
amode identifier[, identifier]...
; (Software part)
amode identifier[,
identifier]... { section_blocks
}
The keyword amode can appear in all parts. In the cpu or memory part you can use amode to map an addressing mode or register bank on a particular address space (definition). When you specify amode=, you map a specific addressing mode on a previously defined addressing mode (reference). The only keywords allowed in an amod_description (cpu part) are attribute, map and mau. The keyword attribute Ynum uniquely identifies the addressing mode.
In the software part you can use amode as part of a cluster definition to change the locating order of sections. See also 4.10 , Section Placing Algorithm.
From cpu or memory part:
cpu { amode near_data { attribute Y3; mau 8; map src=0 size=1k dst=0 amode = far_data; // reference } amode far_data { // definition attribute Y4; mau 8; map src=0 size=32k dst=32k space = address_space; }
From software part:
block ram { cluster data_clstr { attribute w; amode near_data { // Sections with addressing mode // near_data are located here section selection=w; } amode far_data { // Sections with addressing mode // far_data and the stack and heap // are located here section selection=w; heap; stack; } } }
assert ( condition , text
) ; (Software part)
asse ( condition , text
) ; (abbreviated form)
Test condition of virtual address in memory. Generate an error if the assertion fails and give a message with 'text'. condition is specified as one of:
expr1 and expr2 can be any expression or label. The predefined label .addr contains the current address.
block ram { cluster data_clstr { attribute w; amode near_data { section selection=w; assert ( .addr < 256, "page overflow"); // if the condition is false, // the locator generates an error with // the text as message } ... } }
attribute attribute_string ;
(Software part)
attr attribute_string ; (abbreviated form)
attribute = attribute_string
(Software part)
attr = attribute_string (abbreviated form)
With attribute you can assign attributes to sections, clusters or memory blocks. See also the keyword selection.
For sections these attributes are pure supplementary to the standard section attributes. The standard section attributes such as zero page (Y1), blank (B) and executable (X) are set by the compiler (or by the assembler in the case of an assembler program).
With an action attribute after a section (attr= ), you can set section attributes or you can disable section attributes with the - (minus) sign.
The attributes have the following meaning:
num (Section only) Align the section at 2num MAUs.
Ynum (amode and sections only) Identify addressing mode. Indicate that sections with this attribute should be allocated in this cluster.
r (Memory and clusters) Indicate this is a read-only cluster or read-only memory.
w (Memory and clusters) Indicate this is a writable cluster or writable memory.
s (Memory only) Indicate this is special memory, it must not be located.
x (Clusters/sections only) Indicate that the cluster/section is executable.
b (Clusters/sections only) Indicate that clusters/sections should be cleared before locating.
i (Sections only) Indicate that clusters/sections should be copied from ROM to RAM.
f (Clusters/sections only) Indicate that clusters/sections should not be filled and not cleared. This is called a scratch cluster/section.
Default attributes if the attribute keyword is omitted:
sections: The attributes as generated from the assembler/compiler.
clusters: The attributes as indicated by the underlaying memory, thus r for rom and w for ram.
memory: If no attributes defined, the default is writable (w).
From software part:
layout { space address_space { block rom { cluster first_code_clstr { attribute i; // set cluster attribute amode near_code; amode far_code; } }
block ram cluster ram { amode near_data { // Default attribute of cluster // data is 'w', because the // memory is RAM. section selection=w; section selection=b attr=-b; // Sections with attribute b are // are located here, and // attribute 'b' is switched off } . } . } } }
From cpu part:
amode near_data { attribute Y3; //identify code with Y3 mau 8; map src=0 size=1k dst=0 amode = far_data; } ... chips rom_chip attr=r mau=8 size=0x100; chips ram_chip attr=w mau=8 size=0x100; ... // memory attributes
block identifier { block_description } (Software part)
With block you define the contents of a physical area of memory. You can make a block description for each chip you use. Each block has a symbolic name as previously defined by the keyword chips. It is allowed to combine two or more memory chips in one block as long as their total address range is linear, without gaps. The identifier indicates that a memory block starts at the specified chip, no matter how many chips are combined.
layout { space address_space { block ram // Memory block starting at chip ram_chip cluster ram { ... } } } }
(Cpu or memory part)
bus identifier[, identifier]...
{ bus_description } (def)
bus = identifier[|
identifier]... (ref)
With bus you define the physical memory addresses for the chips that are located on the cpu (definition). When you specify bus=, you map a specific address range on a previously defined address bus (reference). You can provide parallel busses by separating each bus with a vertical bar '|'. The only keywords allowed in an bus description are mem, map and mau.
cpu { space address_space { // Specify space 'address_space' for the address_bus // address bus. mau 8; map src=0 size=32k dst=0 bus = address_bus label = rom; map src=32k size=32k dst=32k bus = address_bus label = ram; // ref } bus address_bus { // definition mau 8; mem addr=0 chips=rom_chip; map src=0x100 size=0x7f00 dst=0x100 bus = external_rom_bus; mem addr=32k chips=ram_chip; map src=0x8100 size=0x7f00 dst=0x100 bus = external_ram_bus; } ... }
(Cpu or memory part)
chips identifier[, identifier]...
chips_description (def)
chips = identifier[|
identifier]... [, identifier[| identifier]...]...
(ref)
With chips you describe the chips on the cpu or on your target board (definition). For each chip its size and minimum addressable unit (mau) is specified. With the keyword attr you can define if the memory is read-only. The only three attributes allowed are r for read-only, w for writable, or s for special. If omitted, w is default.
You can use chips= after the keyword mem to specify where a chip is located (reference). You can create chip pairs by separating each chip with a vertical bar '|'.
cpu { bus address_bus { mau 8; mem addr=0 chips=rom_chip; // ref ... } chips rom_chip attr=r mau=8 size=0x100; // def chips ram_chip attr=w mau=8 size=0x100; ... }
(Software part)
cluster cluster_name { cluster_description }
cluster cluster_name[,
cluster_name]... ;
In the software layout part you can define the cluster name and cluster location order. The attributes as valid for clusters (see attribute) can be specified in the first syntax. If you do not specify any attribute, the default attribute r or w is automatically set.
In a cluster description you can not only determine the locate order of sections within the named cluster, but you can also specify stack and heap size, extra process memory, define labels for the process, etc.
space address_space { block rom { cluster first_code_clstr { // The default attribute 'r' of cluster // text is overruled to 'i'. All // sections with attribute 'i' are // located here by default. attribute i; amode near_code; amode far_code; // Sections with addressing mode // near_code or far_cdoe are // located here } block ram { cluster data_clstr { // default attribute 'w' because the // memory is RAM. All writable // sections are located here by default. attribute w; // can be omitted amode near_data { section selection=w; } } }
contiguous { section_blocks } (Software part)
contiguous addr = address { section_blocks }
A contiguous block specifies that all sections named in the block should be located contiguously and in the specified order. The sections will be located back-to-back, only allowing alignment constraint to cause gaps between two consecutive sections.
Alignment constraints of sections are propagated to the contiguous block. This means, for instance, that if the first section should be aligned at even addresses, the contiguous block will start at an even address.
Page constraints will also be propagated to the contiguous block. This means that if a section in the contiguous block may not be located across a specific boundary, the whole contiguous block will not be located over the specified boundaries.
Sections in a contiguous block cannot have conflicting memory requirements, e.g. writable and read-only.
Contiguous blocks can be nested with overlay blocks. A block can have an address (addr=). Addresses within a block are considered offsets relative to the start of the block.
The following example shows a contiguous block with a nested overlay block:
cluster data_clstr { contiguous { section A; section B; overlay { section C; section D; } section E; } .. }
The graphical representation is:
copy section_name [ attr = attribute ] ; (Software part)
copy selection = attribute
[ attr = attribute ] ;
copy ;
The ROM copy of data sections with the attribute i will be copied from ROM to RAM at program startup. With copy you define the placement in memory of these ROM copies. You can specify a specific section by giving the section's name, or select sections with a specific attribute. If you do not specify an argument, the locator locates all ROM copies at the specified location. With attr= you can change the section attributes.
If you do not specify the keyword copy at all, the locator finds a suitable place for ROM copies.
See also the keywords attribute and selection.
space address_space { block rom { ... cluster code_clstr { attribute r; //cluster attribute amode far_code { table; section selection=x; section selection=r; copy; // all ROM copies are located here } } }
cpu { cpu_description } (Cpu
part)
cpu filename
The keyword cpu appears together with software and memory at the highest level in a description file. The actual cpu description starts between the curly braces { }. Normally you do not need to change the cpu part because it is delivered with the product and describes the derivative completely.
The second syntax is the so-called include syntax. The locator opens the file filename and reads the actual cpu description from this file. You must start the included file with cpu again. The filename can contain a complete path including a drive letter (Windows). Parts of filename, or the complete filename can be put in a environment variable. The file is first searched for in the current directory, and secondly in the etc directory relative to the installation directory.
Contents of the description file:
software { ... } cpu target.cpu //cpu part in separate file memory target.mem
See section 3 for a sample contents of a .cpu file.
dst = address (Cpu or memory part)
Specify destination address as part of the keyword map in an amode, space or bus description. For address you can use any decimal, hexadecimal or octal number. You can also use the (standard) Delfee suffix k, for kilo (210) or M, for mega (220). The unit of measure depends on the MAU (minimum addressable unit) of the destination memory space.
cpu { ... amode near_code { attribute Y1; mau 8; // 8-bit addressable map src=0 size=1k dst=0 amode=far_code; } }
fixed address = address ; (Software part)
fixed addr = address ; (abbreviated form)
Define a fixed point in the memory map. The locator allocates the section/cluster preceding the fixed definition and the section/cluster following it as close as possible to the fixed point.
block ram { cluster near_data_clstr { amode near_data { section selection=w; fixed addr = 0x2000; } } cluster far_data_clstr; }
Cluster far_data_clstr will be located with its upper bound at address 0x2000 and cluster near_data_clstr starts at this address. The same can be applied to sections.
gap; (Software part)
gap length = value ;
Reserve a gap with a dynamic size. The locator tries to make the memory space as big as possible. You can use this keyword in a block description to create a gap between clusters, or in a cluster description to create a gap between sections. You can also use the gap keyword in combination with the fixed keyword.
With the second form you can specify a gap of a fixed length. This form can only occur in a block description.
space address_space { block ram { cluster data_clstr { attr w; amode near_data; } // low side mapping gap; // balloon cluster stck; // high side mapping } }
heap heap_description ; (Software
part)
heap ;
Like table and stack, heap is another special section. The section is not created from the .out file, but generated at locate time. To control the size of this special section the keyword length is allowed within the heap description. You can use heap to include dynamic memory for a process.
Heap can only be used if a malloc() function has been implemented.
Two locator labels are used to mark begin and end of the heap, __lc_bh for the begin of heap, and __lc_eh for the end of heap.
Note that if the heap keyword is specified in the description file this does not automatically mean that a heap will always be generated. A heap will only be allocated when its section labels (__lc_bh for begin of heap and __lc_eh for end of heap) are used in the program.
The heap description can be a length specification and/or an attribute specification. See the example.
layout { space address_space { block ram { cluster data_clstr { amode far_data { section selection=w; heap length=100; // Heap of 100 MAUs } } } } }
label identifier ; (Software
part)
label = identifier ; (All
parts)
The first form can be used stand-alone to specify a virtual address in memory by means of a label. The virtual address is label __lc_u_identifier. Note that at C level, all locator labels start with one underscore (the compiler adds another underscore '_').
The second form can only be used as part of another keyword. As part of the keyword reserved you can assign a label to an address range. The start of the address range is identified by label __lc_ub_ identifier. The end of the address range is identified by label __lc_ue_identifier. The keyword label is also allowed as part of the map keyword to assign a name to a block of memory in a space definition.
From the software part:
block ram { cluster data_clstr { attribute w; amode far_data { section selection=w; heap; stack; reserved label=xvwbuffer length=0x10;
// Start address of reserved area is // label __lc_ub_xvwbuffer // End address of reserved area is // label __lc_ue_xvwbuffer } } }
From the cpu part:
space address_space { mau 8; map src=0 size=32k dst=0 bus = address_bus label=rom; map src=32k size=32k dst=32k bus = address_bus label=ram; }
layout { layout_description
} (Software part)
layout filename
The layout part describes the layout of sections in memory. The layout part groups sections into clusters and you can define the name, number and the order of clusters. The layout part describes how these clusters must be allocated into physical RAM and ROM block. The space and block names used in the layout part must be present in the memory part or the cpu part. The cluster definitions can contain fixed addresses as well as definitions of gaps between sections.
software { layout { space address_space { block rom { cluster first_code_clstr { attribute i; amode near_code; } ....
length = length (Cpu,
memory and software part)
leng = length (abbreviated
form)
You can use the keyword length to define the length in MAUs (minimum addressable units) of a certain memory area. length must be a numeric value and can be given either in hex, octal or decimal. As usual, hex numbers must start with '0x' and octal numbers must start with '0'. You can use the suffix k which stands for kilo or M which stands for mega.
You can use length to specify the length of the reserved memory or to specify the stack, heap or gap length. For details see the keywords reserved, stack, heap and gap.
space address_space { block ram { cluster data_clstr { amode far_data { stack leng = 2k; } } } }
load_mod identifier start
= label; (Software part)
load_mod start = label;
With load_mod you are introducing a load module description. This keyword is followed by an optional identifier, representing a load module name with or without the .out extension. The load module itself must be supplied to the locator as a parameter in the invocation. If the identifier is omitted, the load module is taken from the command line.
software { load_mod start = __START; }
or:
software { load_mod hello start = __USER_start; }
map map_description (Cpu or memory part)
Map a memory part, specified as a source address and a size, to a destination address of an amode, space or bus. The unit of measure depends on the MAU of the memory space.
cpu { . amode far_data { attribute Y4; mau 8; map src=0 size=32k dst=32k space=address_space; } space address_space { mau 8; map src=0 size=32k dst=0 bus = address_bus label=rom; map src=32k size=32k dst=32k bus = address_bus label=ram; } bus address_bus { mau 8; mem addr=0 chips=rom_chip; map src=0x100 size=0x7f00 dst=0x100 bus=external_rom_bus; mem addr=32k chips=ram_chip; map src=0x8100 size=0x7f00 dst=0x100 bus=external_ram_bus; } . }
mau number ; (Cpu
or memory part)
mau = number
You can use the keyword mau to specify the minimum addressable unit in bits of a certain memory area. The first form can only be used in an amode, space or bus description. The second form can be used to specify the minimum addressable unit of a chip. Note that mau affects the unit of measure for other keywords. If no mau is specified, the default number is 8 (byte addressable).
cpu { amode near_code { attribute Y1; mau 8; // byte addressable map src=0 size=1k dst=0 amode=far_code; // src is at address 0, // size is 1k byte units // dst is at address 0 } }
mem mem_description ; (Cpu or memory part)
Define the start address of a chip in memory. The only keywords allowed in a mem description are address and chips.
cpu { ... bus internal_bus { mau 8; mem addr=0 chips=rom_chip; // chip 'rom_chip' is located at memory // address 0 ... mem addr=32k chips=ram_chip; // chip 'ram_chip' is located at memory // address 0x8000 ... } chips rom_chip attr=r mau=8 size=0x100; chips ram_chip attr=w mau=8 size=0x100; }
memory { memory_description
} (Memory part)
memory filename
Together with software and cpu, memory introduces a main part of the description file. You can specify the actual memory part between the curly braces { }.
You can use the memory part to describe any additional memory or addresses of peripherals not integrated on the cpu.
The second syntax is the include syntax. In this case, the memory part is defined in a separate file. This included file must start again with memory. The filename can contain a complete path, including a drive letter (Windows). You can put parts of filename, or the complete filename in an environment variable. The file is first searched for in the current directory, and secondly in the etc directory relative to the installation directory.
software { ... } cpu target.cpu memory target.mem //mem part in separate file
See section 5 for a sample contents of a .mem file.
overlay { section_blocks } (Software part)
overlay addr = address { section_blocks }
An overlay block specifies that all sections named in the block should start at the same address.
Page constraints will also be propagated to the overlay block. This means that if a section in the overlay block may not be located across a specific boundary, the whole overlay block will not be located over the specified boundaries.
Sections in an overlay block cannot have conflicting memory requirements, e.g. writable and read-only.
Overlay blocks can be nested with contiguous blocks. Overlay blocks can have an absolute address specified (addr=).
The following example shows an overlay block contiguous block with a nested overlay block:
cluster data_clstr { overlay { section A; contiguous { section B; section C; } contiguous { section D; section E; overlay { section F; section G; } section H; } } .. }
The graphical representation is:
regsfr filename (Cpu or memory part)
Specify a register file generated by the register manager for use by the CrossView debugger.
cpu { . . . regsfr regfile.dat /* * Use file regfile.dat generated by * register manager for CrossView */ }
reserved reserved_description ;
(Software part)
reserved;
Reserve a fixed amount of memory space or reserve as much memory as possible in the memory space. If no length is specified the size of the memory allocation depends on the size of the memory space or the size is limited by a fixed point definition following the reserved allocation.
You can only use the keywords address, attribute, label and length in the reserved description. You can use the keyword reserved in an amode description.
space address_space { block rom { cluster code_clstr { amode near_code { // system reserved // (exception vector) reserved length=0x2 addr=0x24; } } }
(Software part)
section identifier [addr
= address ] [attr = attribute
] ;
section selection = attribute
[addr = address] [attr = attribute];
section can be used in the layout part to specify the location order within a cluster. See also layout.
The identifier is the name of a section.
With addr= you can make a section absolute.
With attr= you can assign new attributes to a section or disable attributes.
See also the keywords address, attribute and selection.
space address_space { block ram { cluster data_clstr { amode near_data { // locate section .data here and set // attribute 'w' section .data attr=w; section selection=b attr=-b; } } } }
selection = attribute
You can use selection after the keywords section or copy to select all sections with (a) specified attribute(s).
If more attributes are specified, only sections with all attributes are selected. If a minus sign '-' precedes the attribute, only sections not having the attribute are selected.
See also the keywords attribute, copy and section.
space address_space { block ram { cluster data_clstr { amode near_data { // select sections with w on and not i. // (select all writable sections which // are not copied from ROM) section selection=-iw; } } } . } ...
size = size (Cpu or memory part)
You can use the keyword size to define the size in minimum addressable units (MAU) of a certain memory area. size must be a numeric value and can be given either in hex, octal or decimal. As usual, hex numbers must start with '0x' and octal numbers must start with '0'. You can use the suffix k which stands for kilo or M which stands for mega.
You can use size to specify the size of a part of memory that must be mapped on another part of memory or to specify the the size of a chip. For details see the keywords map and chips.
cpu { amode near_code { attribute Y1; //identify near_code with Y1 map src=0 size=1k dst=0 amode=far_code; } space address_space { mau 8; map src=0 size=32k dst=0 bus=address_bus label=rom; map src=32k size=32k dst=32k bus=address_bus label=ram; } chips rom_chip attr=r mau=8 size=0x100; chips ram_chip attr=w mau=8 size=0x100; // size of chips }
software { software_description
} (Software part)
software filename
The keyword software appears at the highest level in a description file. The actual software description starts between the curly braces { }.
The second syntax is the so called include syntax. The locator will open file filename and read the actual software description from this file. The first keyword in filename must be software again. The filename can contain a complete path including a drive letter (Windows). You can put parts of filename, or the complete filename in an environment variable. The file is first searched for in the current directory, and secondly in the etc directory relative to the installation directory.
Contents of the description file:
software $(MY_OWN_DESCRIPTION) cpu target.cpu memory target.mem
Environment variable MY_OWN_DESCRIPTION contains the name of a file with contents like:
software { load_mod start = __START; layout { . . . } }
space identifier {
space_description } (Software part)
(Cpu or memory part)
space identifier[, identifier]... { space_description
}
space = identifier
The keyword space can be used in the cpu part, memory part and software part. In the cpu or memory part you can use space to describe a physical memory address space. The only keywords allowed in a space description in the cpu or memory part are mau and map.
In the software part you can use space to describe one or more memory blocks. Each space has a symbolic name as previously defined by the keyword space in the cpu or memory part.
From the cpu part:
cpu { amode far_data { attribute Y4; mau 8; map src=0 size=32k dst=32k space=address_space; } ...
space address_space { // Specify space 'address_space' for the // address_bus address bus. mau 8; map src=0 size=32k dst=0 bus=address_bus label=rom; map src=32k size=32k dst=32k bus=address_bus label=ram; } . }
From the software part:
layout { // define the preferred locating order of sections // in the memory space // (the range is defined in the .cpu file) space address_space { ... // define for each sub-area in the space // the locating order of sections block rom { // Memory block starting at chip rom_chip // define a cluster for read-only sections cluster code_clstr { .... } } . } }
src = address (Cpu or memory part)
Specify source address as part of the keyword map in an amode, space or bus description. For address you can use any decimal, hexadecimal or octal number. You can also use the (standard) Delfee suffix k, for kilo (210) or M, for mega (220). The address is specified in the addressing mode's local MAU (minimum addressable unit) size (default 8 bits).
cpu { ... amode near_code { attribute Y1; mau 8; // 8-bit addressable map src=0 size=1k dst=0 amode=far_code; } }
stack stack_description ; (Software
part)
stack ;
stack is a special form of a section description. The stack is allocated at locate time. The locator only allocates a stack if one is needed. Two special locator labels are associated with the stack space located with keyword stack. The begin of the stack area can be obtained by the locator label __lc_bs, the end address is accessible by means of label __lc_es.
You can only use the keywords attribute and length in the stack description. If you specify stack without a description, the locator tries to make the stack as big as possible. If you do not specify the keyword stack at all, the locator also tries to make the stack as big as possible but at least 100 (MAUs).
space address_space { block ram { cluster data_clstr { amode far_data { section selection=w; stack leng=150; // stack of 150 MAUs ... } } } }
start = label ; (Software part)
Define a start label for a process.
You can use start only within a load module description.
software { load_mod start = system_start; layout { . . } }
table attr = attribute ; (Software part)
table ;
Like stack and heap also table is a special kind of section. Normal sections are generated at compile time, and passed via the assembler and linker to the locator. The stack and heap sections are generated at locate time, with a user requested size.
table is different. The locator is able to generate a copy table. Normally, this table is put in read-only memory. If you want to steer the table location, you can use the table keyword. With table only attribute is allowed. The length is calculated at locate time. table can occur in a cluster description.
space address_space { block rom { ... cluster code_clstr { attribute r; // cluster attribute amode far_code { table; // locate copy table here section selection=x; section selection=r; copy; // all ROM copies are located here } } }
The following Delfee keywords can be abbreviated to unique 4 character words:
Keyword | Abbreviation |
address | addr |
assert | asse |
attribute | attr |
length | leng |
Table G-3: Abbreviation of Delfee keywords
Keyword | Description |
address | Specify absolute memory address |
align | Specify section alignment |
amode | Specify the addressing modes |
assert | Error if assertion failed |
attribute | Assign attributes to clusters, sections, stack or heap |
block | Define physical memory area |
bus | Specify address bus |
chips | Specify cpu chips |
cluster | Specify the order and placement of clusters |
contiguous | Specify a contiguous block of sections |
copy | Define placement of ROM-copies of data sections |
cpu | Define cpu part |
dst | Destination address |
fixed | Define fixed point in memory map |
gap | Reserve dynamic memory gap |
heap | Define heap |
label | Define virtual address label |
layout | Start of the layout description |
length | Length of stack, heap, physical block or reserved space |
load_mod | Define load module (process) |
map | Map a source address on a destination address |
mau | Define minimum addressable unit (in bits) |
mem | Define physical start address of a chip |
memory | Define memory part |
overlay | Specify a block of sections which must be overlaid |
regsfr | Specify register file for use by CrossView |
reserved | Reserve memory |
section | Define how a section must be located |
selection | Specify attributes for grouping sections into clusters |
size | Size of address space or memory |
software | Define the software part |
space | Define an addressing space or specify memory blocks |
src | Source address |
stack | Define a stack section |
start | Give an alternative start label |
table | Define a table section |
Table G-4: Overview of Delfee keywords