[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This chapter contains information for those wishing to write their own CGEN application.
8.1 File Layout | Organization of source files | |
8.2 File Generation Process | Workflow in cgen | |
8.3 Coding Conventions | Coding conventions | |
8.4 Accessing Loaded Data | Reading data from loaded .cpu files | |
8.5 Arch Name References | Architecture names in generated code | |
8.6 String Building | Building long strings and writing them out | |
8.7 COS | Cgen's Object System |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Source files in cgen are organized in a very specific way.(32) It makes it easy to find things.
The best way to create this file is to copy an existing application's file (e.g. cgen-opc.scm) and modify to suit.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This is an overview of cgen workflow.
Currently app-specific code is never compiled in. (33)
There is a #include-like mechanism for loading other files so big architectures can be broken up into several files.
While the architecture description is being loaded, entries not requested are discarded. This happens, for example, when building a simulator: there's no point in keeping instructions specific to a machine that is not being generated. What to keep is based on the MACH and ISA attributes.
e.g. <arch>.sim
The output is written to the output file with with-output-to-file
so
the code must write to (current-output-port)
.
Some files require heavy duty processing of the cpu description. For example the simulator computes the instruction formats from the instruction field lists of each instruction. This computation is deferred to each cgen-<file> procedure that needs it and must be explicitly requested by them. The results are cached so this is only done once of course.
Several opcodes files are built from three sources.
It's not appropriate to put large amounts of C (or perhaps any C) in cgen description files, yet some things are best expressed in some other language (e.g. assembler/disassembler operand parsing/printing).
It seems cleaner to put large amounts of non-machine-generated C in separate files from code generator.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
*UNSPECIFIED*
)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Each kind of description file entry (defined with `define-foo') is recorded in an object of class <foo>.(34) All the data is collected together in an object of class <arch>. (35)
Data for the currently selected architecture is obtained with several access functions.
(current-arch-name) - return symbol that is the name of the arch - this is the name specified with `define-arch' (current-arch-comment) - return the comment specified with `define-arch' (current-arch-atlist) - return the attributes specified with `define-arch' (current-arch-default-alignment) - return a symbol indicated the default alignment - one of aligned, unaligned, forced (current-arch-insn-lsb0?) - return a #t if the least significant bit in a word is numbered 0 - return a #f if the most significant bit in a word is numbered 0 (current-arch-mach-name-list) - return a list of names (as symbols) of all machs in the architecture (current-arch-isa-name-list) - return a list of names (as symbols) of all isas in the architecture For most of the remaining elements, there are three main accessors: [foo is sometimes abbreviated] - current-foo-list - returns list of <foo> objects in the architecture - current-foo-add! - add a <foo> object to the architecture - current-foo-lookup - lookup the <foo> object based on its name <atlist> (current-attr-list) (current-attr-add!) (current-attr-lookup) <enum> (current-enum-list) (current-enum-add!) (current-enum-lookup) <keyword> (current-kw-list) (current-kw-add!) (current-kw-lookup) <isa> (current-isa-list) (current-isa-add!) (current-isa-lookup) <cpu> (current-cpu-list) (current-cpu-add!) (current-cpu-lookup) <mach> (current-mach-list) (current-mach-add!) (current-mach-lookup) <model> (current-model-list) (current-model-add!) (current-model-lookup) <hardware> (current-hw-list) (current-hw-add!) (current-hw-lookup) <ifield> (current-ifld-list) (current-ifld-add!) (current-ifld-lookup) <operand> (current-op-list) (current-op-add!) (current-op-lookup) <insn> (current-insn-list) (current-insn-add!) (current-insn-lookup) <macro-insn> (current-minsn-list) (current-minsn-add!) (current-minsn-lookup) (current-ifmt-list) - return list of computed <iformat> objects (current-sfmt-list) - return list of computed <sformat> objects [there are a few more to be documented, not sure they'll remain as is] |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To simplify writing code generators, system names can be specified with fixed strings rather than having to compute them. The output is post-processed to convert the strings to the actual names. Upper and lower case names are supported.
The ‘prefix’ notion is to segregate different code for the same cpu family. For example, this is used to segregate the ARM ISA from the Thumb ISA.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Output generation uses a combination of writing text out as it is computed and building text for later writing out.
The top level file generator uses string-write
. It takes string-lists
and thunks as arguments and writes each argument in turn to stdout.
String-lists are lists of strings (nested arbitrarily deep). It's cheaper
to cons
long strings together than to use string-append
.
Thunks return string-lists to write out, but isn't computed until all
preceding arguments to `string-write' have been written out. This allows
deferring building up of large amounts of text until it needs to be.
The main procedures for building strings and writing them out are:
Loops over arguments writing them out in turn.
Apply proc to each element in string-list-or-thunk-list and write out the result.
Return list of arguments. This is identical to list
except it
is intended to take string-lists as arguments.
Return list of proc
applied to each element of arg-list
.
This is identical to map
except it is intended to take strings
as arguments.
For small arguments it's just as well to use string-append
.
This is a standard Scheme procedure. The output is also easier to read
when developing interactively. And some subroutines are used in multiple
contexts including some where strings are required, so sometimes you
have to use string-append
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
COS is CGEN's Object System. It's a simple OO system for Guile that was written to provide something useful until Guile had its own. COS will be replaced with GOOPs if the Scheme implementation of CGEN is kept.
The pure Scheme implementation of COS uses vectors to record objects and classes.
A complete list of user-visible functions is at the top of ‘cos.scm’.
Here is a list of the frequently used ones.
Use class-make
to define a class.
name: symbol, <name-of-class> parent-name-list: list of symbols, names of each parent class element-list: list of either symbols or (symbol . initial-value) method-list: list of (symbol . lambda) |
The result is the class's definition. It is usually assigned to a global variable with same name as class's name. Current cgen code always does this. It's not a requirement but it is convention.
Create a new object with new
.
<class-name>
is typically the global variable that recorded
the results of class-make
. The result is a new object of the
requested class. Class elements have either an "undefined" value
or an initial value if one was specified when the class was defined.
Elements (aka members) are read/written with "accessors".
Read accessors are defined with define-getters
, which
creates one procedure for each element, each defined as
(prefix-element-name object)
.
This is a macro so don't quote anything.
Write accessors are defined with define-setters
, which
creates one procedure for each element, each defined as
(prefix-set-element-name! object new-value)
.
This is a macro so don't quote anything.
This can only be used in method definitions (blech, blah blah blah).
This can only be used in method definitions (blech, blah blah blah).
Invoke method method-name
on object
.
The convention is to put this in a cover fn:
(class-name-method-name object arg1 arg2)
.
Same as send
except only usable in methods and is used to invoke
the method in the parent class.
One standard way to create a new object is with make
.
It is a wrapper, defined as
(define (make object . args) (apply send (cons (new object) (cons 'make! args))) ) |
The other standard way to create objects is with vmake
.
args
is a list of option names and arguments.
??? Not completely implemented yet.
The normal way of creating methods is to use method-make!
, not define
them with the class. It's just easier to define them separately.
Create virtual methods created with method-make-virtual!
.
Forwarding a method invocation on one object to another is extremely useful so some utilities have been created to simplify creating forwarding methods.
methods
is a list of method names. A method is created for each one
that forwards the method onto the object contained in element ELM-NAME.
Same as method-make-forward! except that it creates virtual methods.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by Doug Evans on January, 28 2010 using texi2html 1.78.