mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-16 08:25:09 -04:00
improves the board integration HowTo
This commit is contained in:
parent
bd56db2f00
commit
fcfd1e34dd
@ -34,8 +34,8 @@ The `filter` attribute allows to filter the arguments which means the given stri
|
|||||||
to the external program as it is, instead it is preprocessed to allow more flexible arguments which
|
to the external program as it is, instead it is preprocessed to allow more flexible arguments which
|
||||||
are depending on the name of the circuit and so on. If filtering is enabled, the arguments are scanned
|
are depending on the name of the circuit and so on. If filtering is enabled, the arguments are scanned
|
||||||
for either `<?...?>` or `{?...?}` fragments. If such a fragment is found the enclosed text is
|
for either `<?...?>` or `{?...?}` fragments. If such a fragment is found the enclosed text is
|
||||||
evaluated by a code parser. If the code starts with a `=` the following variables content is inserted.
|
evaluated by a code parser. If the code starts with a `=` the following expression is evaluated
|
||||||
The variables that are available are:
|
and inserted. The variables that are available are:
|
||||||
|
|
||||||
- `shortname`: The file name of the current circuit without the suffix.
|
- `shortname`: The file name of the current circuit without the suffix.
|
||||||
- `name`: The file name of the current circuit including the suffix.
|
- `name`: The file name of the current circuit including the suffix.
|
||||||
@ -138,7 +138,7 @@ If you want to print a list containing all the port names and pins, this can be
|
|||||||
There are two methods to make the hdl model run with the frequency given in the circuits
|
There are two methods to make the hdl model run with the frequency given in the circuits
|
||||||
clock component.
|
clock component.
|
||||||
The first one is to define the clock frequency used by the board. This is done by the
|
The first one is to define the clock frequency used by the board. This is done by the
|
||||||
`frequency` attribute in the xml root element:
|
`frequency` attribute in the xml root tag:
|
||||||
```xml
|
```xml
|
||||||
<toolchain name="TinyFPGA BX" frequency="16000000">
|
<toolchain name="TinyFPGA BX" frequency="16000000">
|
||||||
...
|
...
|
||||||
@ -149,7 +149,7 @@ signal provided by the board to match the clock frequency given in the circuit.
|
|||||||
Although this is very easy, it is also problematic because the clock is generated
|
Although this is very easy, it is also problematic because the clock is generated
|
||||||
by flipflops, not by the pll which is usually available on the fpga.
|
by flipflops, not by the pll which is usually available on the fpga.
|
||||||
|
|
||||||
To utilize the pll available in the fpga a specific piece of hdl code needs to be
|
To utilize the pll available in the fpga, a specific piece of hdl code needs to be
|
||||||
generated. This is done by defining a clock generator instead of simply define the
|
generated. This is done by defining a clock generator instead of simply define the
|
||||||
frequency:
|
frequency:
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ frequency:
|
|||||||
...
|
...
|
||||||
</toolchain>
|
</toolchain>
|
||||||
```
|
```
|
||||||
If the `clockGenerator` attribute is used, the circuits hdl code is generated
|
If the `clockGenerator` attribute is given, the circuits hdl code is generated
|
||||||
in a way that either `clockGenerator.v` or `clockGenerator.vhdl` is used to
|
in a way that either `clockGenerator.v` or `clockGenerator.vhdl` is used to
|
||||||
generate the clock. The hdl code generator assumes that the clock generator
|
generate the clock. The hdl code generator assumes that the clock generator
|
||||||
has a input port `cin` and a output port `cout`.
|
has a input port `cin` and a output port `cout`.
|
||||||
@ -169,17 +169,19 @@ folder for a more complex example.
|
|||||||
|
|
||||||
## The HGS language
|
## The HGS language
|
||||||
|
|
||||||
|
### General
|
||||||
|
|
||||||
The HGS language (HDL Generator Scripting language) is used as a template
|
The HGS language (HDL Generator Scripting language) is used as a template
|
||||||
engine to create files dynamically. There are two main usages: At first
|
engine to create files dynamically. There are two main usages: At first
|
||||||
this language is used to define the VHDL and Verilog templates which are
|
this language is used to define the VHDL and Verilog templates which are
|
||||||
necessary to export a circuit to VHDL or Verilog.
|
necessary to export a circuit to VHDL or Verilog.
|
||||||
|
|
||||||
Second the GDS language is used to generate the board specific files which are
|
Second the HGS language is used to generate the board specific files which are
|
||||||
necessary to run a circuit on a specific board. HGS is a simple, dynamic,
|
necessary to run a circuit on a specific board. HGS is a simple, dynamic,
|
||||||
interpreted language designed for file templating.
|
interpreted language designed for file templating.
|
||||||
|
|
||||||
To avoid a couple of common mistakes by using a dynamic language it uses
|
To avoid a couple of common mistakes by using a dynamic language it uses
|
||||||
a uncommon approach to deal with assignments. To declare a new variable
|
a uncommon approach to deal with variables. To declare a new variable
|
||||||
you have to use the `:=` operator. This is only possible if the new variables
|
you have to use the `:=` operator. This is only possible if the new variables
|
||||||
does not exist. Once the new variable is created an assignment to the variable
|
does not exist. Once the new variable is created an assignment to the variable
|
||||||
is done by the `=` operator. This is only possible if the variable already
|
is done by the `=` operator. This is only possible if the variable already
|
||||||
@ -193,5 +195,137 @@ But this code fails with an error message:
|
|||||||
a:=0.1;
|
a:=0.1;
|
||||||
a=true;
|
a=true;
|
||||||
```
|
```
|
||||||
The variable `a` is declared as a float. It is not possible to assign a bool to it.
|
The variable `a` is declared as a float. It is not possible to assign a
|
||||||
|
bool to it.
|
||||||
|
|
||||||
|
### File Creation
|
||||||
|
|
||||||
|
A template allways begins with plain text which is copied to the file to generate.
|
||||||
|
Special actions - data evaluations or control structures - are delimited
|
||||||
|
by `{?` and `?}` or `<?` and `?>`. Because the `.config` files are XML files the
|
||||||
|
`{?` and `?}` variant is easier to use in most cases.
|
||||||
|
|
||||||
|
If you want to create a file which creates the clock period in ns you can use the
|
||||||
|
following template:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<file name="clock.txt" overwrite="true" filter="true">
|
||||||
|
<content>clock period is {? period:=1000000000/model.frequency; print(period);?}ns</content>
|
||||||
|
</file>
|
||||||
|
```
|
||||||
|
or in short:
|
||||||
|
```xml
|
||||||
|
<file name="clock.txt" overwrite="true" filter="true">
|
||||||
|
<content>clock period is {?=1000000000/model.frequency?}ns</content>
|
||||||
|
</file>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Control Structures
|
||||||
|
|
||||||
|
All the most common control structures are available:
|
||||||
|
|
||||||
|
The `for` statement:
|
||||||
|
```
|
||||||
|
for ( i:=0; i<10; i++) {
|
||||||
|
println(i);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `if` statement:
|
||||||
|
|
||||||
|
```
|
||||||
|
if (a<0) {
|
||||||
|
println(a);
|
||||||
|
} else {
|
||||||
|
println(-a);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `while` statement:
|
||||||
|
|
||||||
|
```
|
||||||
|
while (a<10) {
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `repeat` statement:
|
||||||
|
|
||||||
|
```
|
||||||
|
repeat {
|
||||||
|
a++;
|
||||||
|
} until a>=10;
|
||||||
|
```
|
||||||
|
|
||||||
|
It is possible to declare a function:
|
||||||
|
|
||||||
|
```
|
||||||
|
func fibu(n){
|
||||||
|
if (n<2)
|
||||||
|
return n;
|
||||||
|
else
|
||||||
|
return fibu(n-1)+fibu(n-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(fibu(10));
|
||||||
|
```
|
||||||
|
Closures are also supported:
|
||||||
|
|
||||||
|
```
|
||||||
|
func create() {
|
||||||
|
inner:=0;
|
||||||
|
return func(){
|
||||||
|
inner++;
|
||||||
|
return inner;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
a:=create();
|
||||||
|
b:=create();
|
||||||
|
|
||||||
|
print(a()+","+a()+","+b());
|
||||||
|
```
|
||||||
|
The output is "1,2,1".
|
||||||
|
|
||||||
|
### Built-In Functions
|
||||||
|
|
||||||
|
The following functions are predeclared:
|
||||||
|
|
||||||
|
`bitsNeededFor(int)` returns the number of bits needed to store the given integer value.
|
||||||
|
|
||||||
|
`ceil(float)` returns the smallest integer number greater than the given float.
|
||||||
|
|
||||||
|
`floor(float)` returns the largest integer number smaller than the given float.
|
||||||
|
|
||||||
|
`round(float)` returns the integer number closest to the given float.
|
||||||
|
|
||||||
|
`float(arg)` converts the given number to a float.
|
||||||
|
|
||||||
|
`min(a,b,...)` returns the min value of all given arguments.
|
||||||
|
|
||||||
|
`max(a,b,...)` returns the max value of all given arguments.
|
||||||
|
|
||||||
|
`abs(num)` if the number is positive, the number is returned. otherwise -num is returned.
|
||||||
|
|
||||||
|
`print(arg)` prints the given argument
|
||||||
|
|
||||||
|
`println(arg)` prints the given argument followed by a new line.
|
||||||
|
|
||||||
|
`printf(str,arg,...)` the well known C-style printf function.
|
||||||
|
|
||||||
|
`format(str,arg,...)` similar to `printf`, but the result is retuned as a string.
|
||||||
|
|
||||||
|
`log(arg)` prints the given argument to the log file.
|
||||||
|
|
||||||
|
`isPresent(arg)` returns true if the given arguments exists.
|
||||||
|
|
||||||
|
`panic(msg)` creates a runtime panic. Throws a java exception with the given message.
|
||||||
|
|
||||||
|
`splitString(string)` splits the given string in substrings.
|
||||||
|
Returns an array of strings. The separator chars are " \n\r\t,:;"
|
||||||
|
|
||||||
|
`sizeOf(var)` returns the size of an array or a map.
|
||||||
|
|
||||||
|
`newMap()` creates a new empty map.
|
||||||
|
|
||||||
|
`newList()` creates a new empty list.
|
@ -472,6 +472,24 @@ public class ParserTest extends TestCase {
|
|||||||
assertEquals(1L, inc.call());
|
assertEquals(1L, inc.call());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFunctionClosure2() throws IOException, ParserException, HGSEvalException {
|
||||||
|
String c = exec(
|
||||||
|
"<?" +
|
||||||
|
"func create() {" +
|
||||||
|
" inner:=0; " +
|
||||||
|
" return func(){" +
|
||||||
|
" inner++; " +
|
||||||
|
" return inner;" +
|
||||||
|
" };" +
|
||||||
|
"}" +
|
||||||
|
"a:=create();" +
|
||||||
|
"b:=create();" +
|
||||||
|
"print(a()+\",\"+a()+\",\"+b());" +
|
||||||
|
"?>").toString();
|
||||||
|
|
||||||
|
assertEquals("1,2,1", c);
|
||||||
|
}
|
||||||
|
|
||||||
public static final class TestClass {
|
public static final class TestClass {
|
||||||
private long inner;
|
private long inner;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user