HDLRuby 2.1.2 → 2.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/HDLRuby.gemspec +4 -2
- data/README.md +84 -25
- data/lib/HDLRuby/hdr_samples/mei8.rb +2 -2
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +2 -2
- data/lib/HDLRuby/hdr_samples/with_channel.rb +11 -13
- data/lib/HDLRuby/hdr_samples/with_memory.rb +123 -0
- data/lib/HDLRuby/hdrcc.rb +62 -55
- data/lib/HDLRuby/high_samples/with_top_unshift.rb +29 -0
- data/lib/HDLRuby/high_samples/with_unshift.rb +25 -0
- data/lib/HDLRuby/hruby_high.rb +120 -10
- data/lib/HDLRuby/hruby_low.rb +32 -0
- data/lib/HDLRuby/hruby_low2vhd.rb +5 -1
- data/lib/HDLRuby/hruby_verilog.rb +1 -1
- data/lib/HDLRuby/std/channel.rb +488 -111
- data/lib/HDLRuby/std/memory.rb +328 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c4b9674ac3417d63639cd42264b6e5587a64a4fb801587adf864e8617a118931
|
4
|
+
data.tar.gz: 1800e2649fd77e1e7e34f44bd5357e9425c35ba9771fad8f946bc992a6cb59e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 485fb494e96a3a1dcabbd9dcf6a70c4ca8a6ba3dd84dd3229450a0f3165aa27583f43bc8c07bfe61df98441426c0b66b703a8c2057f9948fb9b82bbfebbb9eb6
|
7
|
+
data.tar.gz: 39ec1e3ff2b4a24b6a4adf8403738d31de1a0009e48c043d276ee5f3db3cb840d82da1c37eb208f4bb214b2c008e9b264983c1b750704b8646d6b6f25fea3894
|
data/HDLRuby.gemspec
CHANGED
@@ -28,7 +28,9 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.require_paths = ["lib","lib/HDLRuby"]
|
29
29
|
|
30
30
|
spec.required_ruby_version = '>= 2.0'
|
31
|
-
spec.add_development_dependency "bundler", "~> 2.0.1"
|
32
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
# spec.add_development_dependency "bundler", "~> 2.0.1"
|
32
|
+
# spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_development_dependency "bundler", ">= 2.0.1"
|
34
|
+
spec.add_development_dependency "rake", ">= 10.0"
|
33
35
|
# spec.add_development_dependency "minitest", "~> 5.0"
|
34
36
|
end
|
data/README.md
CHANGED
@@ -54,6 +54,7 @@ Where:
|
|
54
54
|
| `-D, --debug` | Set the HDLRuby debug mode |
|
55
55
|
| `-t, --top system`| Specify the top system describing the circuit to compile |
|
56
56
|
| `-p, --param x,y,z` | Specify the generic parameters |
|
57
|
+
| `--version ` | Print the version number, then exit |
|
57
58
|
| `-h, --help` | Show the help message |
|
58
59
|
|
59
60
|
__Notes__:
|
@@ -1059,8 +1060,11 @@ __Note__:
|
|
1059
1060
|
```
|
1060
1061
|
- Parallel mode can be set the same way using `par`.
|
1061
1062
|
|
1062
|
-
|
1063
|
-
|
1063
|
+
### Extra features for the description of behaviors
|
1064
|
+
|
1065
|
+
#### Single-statement behaviors
|
1066
|
+
|
1067
|
+
It often happens that a behavior contains only one statement. In such a case, the description can be shortened using the `at` operator as follows:
|
1064
1068
|
|
1065
1069
|
```ruby
|
1066
1070
|
( statement ).at(<list of events>)
|
@@ -1087,6 +1091,41 @@ For sake of consistency, this operator can also be applied on block statements a
|
|
1087
1091
|
end ).at(clk.posedge)
|
1088
1092
|
```
|
1089
1093
|
|
1094
|
+
#### Insertion of statements at the beginning of a block
|
1095
|
+
|
1096
|
+
By default, the statements of a block are added in order of appearance in the code. However, it is also possible to insert statements at the top of the current block using the unshift command within a block as follows:
|
1097
|
+
|
1098
|
+
```ruby
|
1099
|
+
unshift do
|
1100
|
+
<list of statements>
|
1101
|
+
end
|
1102
|
+
```
|
1103
|
+
|
1104
|
+
For example the following code inserts two statements at the beginning of the current block:
|
1105
|
+
|
1106
|
+
```ruby
|
1107
|
+
par do
|
1108
|
+
x <= y + z
|
1109
|
+
unshift do
|
1110
|
+
a <= b - c
|
1111
|
+
u <= v & w
|
1112
|
+
end
|
1113
|
+
end
|
1114
|
+
```
|
1115
|
+
|
1116
|
+
The code above will actually result in the following block:
|
1117
|
+
|
1118
|
+
```ruby
|
1119
|
+
par do
|
1120
|
+
a <= b - c
|
1121
|
+
u <= v & w
|
1122
|
+
x <= y + z
|
1123
|
+
end
|
1124
|
+
```
|
1125
|
+
|
1126
|
+
__Note__:
|
1127
|
+
- While of no practical use for simple circuit description, this feature can be used in advanced generic component descriptions.
|
1128
|
+
|
1090
1129
|
|
1091
1130
|
## Events
|
1092
1131
|
<a name="events"></a>
|
@@ -1568,11 +1607,11 @@ The type puns include `to_bit`, `to_unsigned` and `to_signed` that convert expre
|
|
1568
1607
|
|
1569
1608
|
```ruby
|
1570
1609
|
[ up: signed[3..0], down: unsigned[3..0] ].inner :sig
|
1571
|
-
sig.to_bit <=
|
1610
|
+
sig.to_bit <= _b01010011
|
1572
1611
|
```
|
1573
1612
|
|
1574
1613
|
The type casts change both the type and the value and are used to adjust the width of the types. They can only be applied to vectors of `bit`, `signed` or `unsinged` and can only increase the bit width (bit width can be truncated using the selection operator, please refer to the [next section](#concat)).
|
1575
|
-
These operators comprise the bit width conversions: `ljust`, `rjust`, `zext` and `sext
|
1614
|
+
These operators comprise the bit width conversions: `ljust`, `rjust`, `zext` and `sext`.
|
1576
1615
|
|
1577
1616
|
More precisely, the bit width conversions operate as follows:
|
1578
1617
|
|
@@ -1603,14 +1642,6 @@ More precisely, the bit width conversions operate as follows:
|
|
1603
1642
|
sig1 <= sig0.sext(12)
|
1604
1643
|
```
|
1605
1644
|
|
1606
|
-
Finally, the bit endianness conversions operate as follows:
|
1607
|
-
|
1608
|
-
- `to_big` ensures the type of the converted expression is big endian. If the initial expression is already big endian, it is left as is, otherwise its bits are reversed.
|
1609
|
-
|
1610
|
-
- `to_little` ensures the type of the converted expression is little endian. If the initial expression is already little endian, it is left as is, otherwise its bits are reversed.
|
1611
|
-
|
1612
|
-
- `reverse` always reverses the bit order of the expression.
|
1613
|
-
|
1614
1645
|
|
1615
1646
|
#### Concatenation and selection operators
|
1616
1647
|
<a name="concat"></a>
|
@@ -1644,7 +1675,7 @@ Concatenation and selection are done using the `[]` operator as follows:
|
|
1644
1675
|
#### Implicit conversions
|
1645
1676
|
<a name="implicit"></a>
|
1646
1677
|
|
1647
|
-
When there is no ambiguity
|
1678
|
+
When there is no ambiguity, HDLRuby will automatically insert conversion operators when two types are not compatible with one another. The cases where such implicit conversions are applied are summarized in the following tables where:
|
1648
1679
|
|
1649
1680
|
- `operator` is the operator in use
|
1650
1681
|
- `result width` is the width of the result's type
|
@@ -2268,8 +2299,9 @@ In order to get information about the current state of the hardware description
|
|
2268
2299
|
| `is_seq?` | bit | tells if current parallel block is sequential|
|
2269
2300
|
| `is_clocked?` | bit | tells if current behavior is clocked (activated on a sole rising or falling edge of a signal) |
|
2270
2301
|
| `cur_block` | block | gets the current block |
|
2271
|
-
| `cur_behavior` | behavior | gets the current behavior
|
2272
|
-
| `cur_systemT` | system | gets the current system
|
2302
|
+
| `cur_behavior` | behavior | gets the current behavior |
|
2303
|
+
| `cur_systemT` | system | gets the current system |
|
2304
|
+
| `top_block ` | block | gets the top block of the current behavior |
|
2273
2305
|
| `one_up` | block/system | gets the upper construct (block or system) |
|
2274
2306
|
| `last_one` | any | last declared construct |
|
2275
2307
|
|
@@ -2730,15 +2762,21 @@ end
|
|
2730
2762
|
|
2731
2763
|
This library provides a unified interface to complex communication protocols through a new kind of components called the channels that abstract the details of communication protocols. The channels can be used similarly to the ports of a system and are used through a unified interface so that changing the kind of channel, i.e., the communication protocol, does not require any modification of the code.
|
2732
2764
|
|
2765
|
+
### Using a channel
|
2766
|
+
|
2733
2767
|
A channel is used similarly to a pipe: it has an input where data can be written and an output where data can be read. The ordering of the data and the synchronization depend on the internals of the channel, e.g., a channel can be FIFO or LIFO. The interaction with the channel is done using the following methods:
|
2734
2768
|
|
2735
|
-
* `output <name>`: generate ports in the system for writing to the channel and associate them to `name`
|
2736
2769
|
* `input <name>`: generate ports in the system for reading from the channel amd associate them to `name`
|
2770
|
+
* `output <name>`: generate ports in the system for writing to the channel and associate them to `name`
|
2771
|
+
* `inout <name>`: generate ports in the system for reading and writing to the channel and associate them to `name`
|
2772
|
+
* `inner <name>`: generates inner signals for accessing directly the channel
|
2773
|
+
|
2774
|
+
__Note__: `input`, `output`, `inout` and `inner` for channels work similarly to the ones of data types for declaring signals. In particular, `input`, `output` and `inout` are to be used in systems that do not include the channel and `inner` is to be used in the system that include the channel.
|
2737
2775
|
|
2738
2776
|
When the channel ports are declared, they can be accessed using the following methods depending on whether they are writing or reading ports:
|
2739
2777
|
|
2740
|
-
* `write(<
|
2741
|
-
* `read(<
|
2778
|
+
* `write(<args>) <block>`: write to the channel and execute `block` when `write` completes. `args` is a list of arguments required for performing the write that depend on the channel.
|
2779
|
+
* `read(<args>) <block>`: read the channel and execute `block` when the read completes. `args` is a list of arguments required for performing the write that depend on the channel.
|
2742
2780
|
|
2743
2781
|
For example, a system sending successive 8-bit values through a channel can be described as follows:
|
2744
2782
|
|
@@ -2763,6 +2801,22 @@ end
|
|
2763
2801
|
|
2764
2802
|
__Note__: In the code above, the channel is passed as generic argument of the system.
|
2765
2803
|
|
2804
|
+
### Channel branches
|
2805
|
+
|
2806
|
+
Some channel may include several branches, they are accessed by name using the following method:
|
2807
|
+
|
2808
|
+
* `branch(<name>)`: gets branch named `name` from the channel. This name can be actually be any ruby object (e.g., a number) but it will be converted internally to a ruby symbol.
|
2809
|
+
|
2810
|
+
A branch is a full fledge channel and is used identically. For instance the following code get access to branch number 0 of channel `ch`, get its inputs port, read it and put the result in signal `val` on rising edges of signal `clk`:
|
2811
|
+
|
2812
|
+
```ruby
|
2813
|
+
br = ch.branch(0)
|
2814
|
+
br.input
|
2815
|
+
par(clk.posedge) { br.read(val) }
|
2816
|
+
```
|
2817
|
+
|
2818
|
+
### Declaring a channel
|
2819
|
+
|
2766
2820
|
A new channel is declared like using the keyword `channel` as follows:
|
2767
2821
|
|
2768
2822
|
```ruby
|
@@ -2773,19 +2827,24 @@ Where `name` is the name of the channel and `block` is a procedure block describ
|
|
2773
2827
|
|
2774
2828
|
* `reader_input <list of names>`: declares the input ports on the reader side. The list must give the names of the inner signals of the channel that can be read using the reader procedure.
|
2775
2829
|
* `reader_output <list of names>`: declares the output ports on the reader side. The list must give the names of the inner signals of the channel that can be written using the reader procedure.
|
2776
|
-
* `
|
2777
|
-
* `
|
2778
|
-
* `
|
2830
|
+
* `reader_inout <list of names>`: declares the inout ports on the reader side. The list must give the names of the inner signals of the channel that can be written using the reader procedure.
|
2831
|
+
* `writer_input <list of names>`: declares the input ports on the writer side. The list must give the names of the inner signals of the channel that can be read using the writer procedure.
|
2832
|
+
* `writer_output <list of names>`: declares the output ports on the writer side. The list must give the names of the inner signals of the channel that can be written using the writer procedure.
|
2833
|
+
* `writer_inout <list of names>`: declares the inout ports on the writer side. The list must give the names of the inner signals of the channel that can be written using the writer procedure.
|
2834
|
+
* `accesser_input <list of names>`: declares the input ports on both the reader and writer side. The list must give the names of the inner signals of the channel that can be read using the writer procedure.
|
2835
|
+
* `accesser_output <list of names>`: declares the output ports on both the reader and writer side. The list must give the names of the inner signals of the channel that can be written using the writer procedure.
|
2836
|
+
* `accesser_inout <list of names>`: declares the inout ports on both the reader and writer side. The list must give the names of the inner signals of the channel that can be written using the writer procedure.
|
2779
2837
|
* `reader <block>`: defines the reader's access procedure.
|
2780
2838
|
This procedure is invoked by method `read` of the channel (please refer to the previous example).
|
2781
|
-
The block
|
2839
|
+
The first argument of the block must be the following:
|
2782
2840
|
- `blk`: the block to execute when the read completes.
|
2783
|
-
|
2841
|
+
Other arguments can be freely defined, and will be required by the `read` method.
|
2784
2842
|
* `writer < block>`: defines the writer's access procedure.
|
2785
2843
|
This procedure is invoked by method `write` of the channel (please refer to the previous example).
|
2786
|
-
The block
|
2844
|
+
The first argument of the block must be the following:
|
2787
2845
|
- `blk`: the block to execute when the write completes.
|
2788
|
-
|
2846
|
+
Other arguments can be freely defined, and will be required by the `write` command.
|
2847
|
+
* `brancher(name) <block>`: defines branch named +name+ described in `block`. The content of block can be any content valid for a channel, with the additional possiblity to access the internals of the upper channel.
|
2789
2848
|
|
2790
2849
|
For example, a channel implemented by a simple register of generic type `typ`, that can be set to 0 using the `reset` command can be described as follows:
|
2791
2850
|
|
@@ -25,9 +25,9 @@ system :mei8 do |prog_file = "./prog.obj"|
|
|
25
25
|
instance :prog do
|
26
26
|
[7..0].input :addr # The address bus
|
27
27
|
[7..0].output :instr # The instruction bus
|
28
|
-
bit[7..0][-256].constant
|
28
|
+
bit[7..0][-256].constant mem: # The content of the memory
|
29
29
|
File.readlines(prog_file).map {|l| l.split[0].to_i(2)}
|
30
|
-
instr <=
|
30
|
+
instr <= mem[addr] # The access procedure
|
31
31
|
end
|
32
32
|
|
33
33
|
# The registers.
|
@@ -25,11 +25,11 @@ system :mei8 do |prog_file = "./prog_encrypt.obj"|
|
|
25
25
|
instance :prog do
|
26
26
|
[7..0].input :addr # The address bus
|
27
27
|
[7..0].output :instr # The instruction bus
|
28
|
-
bit[7..0][-256].constant
|
28
|
+
bit[7..0][-256].constant mem: # The content of the memory
|
29
29
|
( File.readlines(prog_file).map {|l| l.split[0] }.select do |l|
|
30
30
|
["0","1"].include?(l[2])
|
31
31
|
end.map {|l| l[2..9] } )
|
32
|
-
instr <=
|
32
|
+
instr <= mem[addr] # The access procedure
|
33
33
|
end
|
34
34
|
|
35
35
|
# The registers.
|
@@ -20,17 +20,15 @@ channel(:handshaker) do |typ|
|
|
20
20
|
# Sets the writer output ports.
|
21
21
|
writer_output :buf, :read_valid, :read_ready
|
22
22
|
|
23
|
-
# Defines the reset command for the channel.
|
24
|
-
command(:reset) do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
end
|
23
|
+
# # Defines the reset command for the channel.
|
24
|
+
# command(:reset) do
|
25
|
+
# # Fully locked reader side.
|
26
|
+
# read_valid <= 0
|
27
|
+
# read_ready <= 0
|
28
|
+
# # Fully unlocked writer side.
|
29
|
+
# write_valid <= 1
|
30
|
+
# write_ready <= 1
|
31
|
+
# end
|
34
32
|
|
35
33
|
# Defines the reader's access procedure.
|
36
34
|
reader do |blk,target|
|
@@ -106,8 +104,8 @@ system :hs_test do
|
|
106
104
|
# Declares the handshaker
|
107
105
|
handshaker([8]).(:hs)
|
108
106
|
|
109
|
-
# Sets the reset.
|
110
|
-
|
107
|
+
# # Sets the reset.
|
108
|
+
# par(rst.posedge) { hs.reset }
|
111
109
|
|
112
110
|
# Instantiate the producer.
|
113
111
|
producer8(hs).(:producerI).(clk,rst)
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'std/memory.rb'
|
2
|
+
|
3
|
+
include HDLRuby::High::Std
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
# A system accessing a memory.
|
9
|
+
system :periph do |mem|
|
10
|
+
# Inputs of the peripheral: clock and reset.
|
11
|
+
input :clk, :rst
|
12
|
+
|
13
|
+
# Inner 8-bit counter for generating addresses.
|
14
|
+
[8].inner :address
|
15
|
+
# Inner 8-bit counter for generating values.
|
16
|
+
[8].inner :value
|
17
|
+
# The memory port.
|
18
|
+
mem.inout :memP
|
19
|
+
|
20
|
+
|
21
|
+
# The value production process
|
22
|
+
par(clk.posedge) do
|
23
|
+
hif(rst) do
|
24
|
+
address <= 0
|
25
|
+
end
|
26
|
+
memP.read(address,value) do
|
27
|
+
value <= value + 1
|
28
|
+
memP.write(address,value) { address <= address + 1 }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# A system producing data and writing it to a memory.
|
34
|
+
system :producer do |mem|
|
35
|
+
# Clock and reset.
|
36
|
+
input :clk, :rst
|
37
|
+
# The memory port.
|
38
|
+
mem.output :memP
|
39
|
+
|
40
|
+
# Inner 8-bit counter for generating addresses and values
|
41
|
+
[8].inner :count
|
42
|
+
|
43
|
+
# The value production process.
|
44
|
+
par(clk.posedge) do
|
45
|
+
hif(rst) { count <= 0 }
|
46
|
+
helse do
|
47
|
+
memP.write(count,count) { count <= count + 1 }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# A system consuming data from a memory.
|
53
|
+
system :consumer do |mem|
|
54
|
+
# Clock and reset.
|
55
|
+
input :clk, :rst
|
56
|
+
# The accumumated consumed data list.
|
57
|
+
[8].output :sum
|
58
|
+
# The memory port.
|
59
|
+
mem.input :memP
|
60
|
+
|
61
|
+
# Inner 8-bit counter for generating addresses and values
|
62
|
+
[8].inner :count
|
63
|
+
# Memory access result.
|
64
|
+
[8].inner :res
|
65
|
+
|
66
|
+
# The value production process.
|
67
|
+
par(clk.posedge) do
|
68
|
+
hif(rst) do
|
69
|
+
count <= 255
|
70
|
+
sum <= 0
|
71
|
+
end
|
72
|
+
helse do
|
73
|
+
memP.read(count,res) do
|
74
|
+
count <= count + 1
|
75
|
+
sum <= sum + res
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
# A system testing the memory.
|
84
|
+
system :mem_test do
|
85
|
+
input :clk,:rst
|
86
|
+
|
87
|
+
# Declares a dual-port 8-bit data and address synchronous memory
|
88
|
+
# on negative edge of clk.
|
89
|
+
mem_sync(2,[8],256,clk.negedge,rst,[:rst,:rst]).(:memI)
|
90
|
+
|
91
|
+
# Instantiate the producer to access port 1 of the memory.
|
92
|
+
periph(memI.branch(1)).(:periphI).(clk,rst)
|
93
|
+
# periph(memI).(:periphI).(clk,rst)
|
94
|
+
memI.branch(0).inner :mem0
|
95
|
+
|
96
|
+
# Inner 8-bit counter for generating addresses.
|
97
|
+
[8].inner :address
|
98
|
+
# Inner 8-bit counter for generating values.
|
99
|
+
[8].inner :value
|
100
|
+
|
101
|
+
# Access the memory.
|
102
|
+
par(clk.posedge) do
|
103
|
+
hif(rst) do
|
104
|
+
address <= 255; value <= 128
|
105
|
+
end
|
106
|
+
# memI.write(0,address,value) { address <= address - 1 }
|
107
|
+
mem0.write(address,value) { address <= address - 1 }
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
[8].inner :sum
|
112
|
+
|
113
|
+
# Declares a dual edge 8-bit data and address memory.
|
114
|
+
mem_dual([8],256,clk,rst, raddr: :rst,waddr: :rst).(:memDI)
|
115
|
+
|
116
|
+
# Instantiate the producer to access port waddr of the memory.
|
117
|
+
producer(memDI.branch(:waddr)).(:producerI).(clk,rst)
|
118
|
+
|
119
|
+
# Instantiate the producer to access port raddr of the memory.
|
120
|
+
consumer(memDI.branch(:raddr)).(:consumerI).(clk,rst,sum)
|
121
|
+
|
122
|
+
|
123
|
+
end
|
data/lib/HDLRuby/hdrcc.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'fileutils'
|
4
4
|
require 'HDLRuby'
|
5
5
|
require 'HDLRuby/hruby_check.rb'
|
6
|
-
require 'ripper'
|
6
|
+
# require 'ripper'
|
7
7
|
require 'HDLRuby/hruby_low2high'
|
8
8
|
require 'HDLRuby/hruby_low2c'
|
9
9
|
require 'HDLRuby/hruby_low2vhd'
|
@@ -25,6 +25,8 @@ require 'HDLRuby/hruby_verilog.rb'
|
|
25
25
|
require 'HDLRuby/backend/hruby_allocator'
|
26
26
|
require 'HDLRuby/backend/hruby_c_allocator'
|
27
27
|
|
28
|
+
require 'HDLRuby/version.rb'
|
29
|
+
|
28
30
|
##
|
29
31
|
# HDLRuby compiler interface program
|
30
32
|
#####################################
|
@@ -250,7 +252,7 @@ $optparse = OptionParser.new do |opts|
|
|
250
252
|
opts.separator "* `<output file>` is the output file"
|
251
253
|
opts.separator ""
|
252
254
|
opts.separator "Options:"
|
253
|
-
|
255
|
+
|
254
256
|
opts.on("-y", "--yaml", "Output in YAML format") do |y|
|
255
257
|
$options[:yaml] = y
|
256
258
|
end
|
@@ -311,7 +313,12 @@ $optparse = OptionParser.new do |opts|
|
|
311
313
|
opts.on("-p", "--param x,y,z", "Specify the generic parameters") do |p|
|
312
314
|
$options[:param] = p
|
313
315
|
end
|
314
|
-
opts.
|
316
|
+
opts.on("--version", "Print the version number, then exit") do
|
317
|
+
puts "hdrcc: HDLRuby #{HDLRuby::VERSION} compiler"
|
318
|
+
exit
|
319
|
+
end
|
320
|
+
# opts.on_tail("-h", "--help", "Show this message") do
|
321
|
+
opts.on("-h", "--help", "Show this message") do
|
315
322
|
puts opts
|
316
323
|
exit
|
317
324
|
end
|
@@ -422,10 +429,10 @@ if $allocate_range then
|
|
422
429
|
$allocate_range = [$allocate_range[0]..$allocate_range[1],
|
423
430
|
$allocate_range[2]].compact
|
424
431
|
# Create the allocator.
|
425
|
-
allocator = HDLRuby::Low::Allocator.new(*$allocate_range)
|
432
|
+
$allocator = HDLRuby::Low::Allocator.new(*$allocate_range)
|
426
433
|
$non_hdlruby.each do |code|
|
427
434
|
# Try the C allocator.
|
428
|
-
code.c_code_allocate(allocator)
|
435
|
+
code.c_code_allocate($allocator)
|
429
436
|
end
|
430
437
|
end
|
431
438
|
# Generates its code.
|
@@ -449,9 +456,9 @@ elsif $options[:hdr] then
|
|
449
456
|
$output << $top_system.to_high
|
450
457
|
elsif $options[:clang] then
|
451
458
|
# top_system = $top_instance.to_low.systemT
|
452
|
-
top_system = $top_system
|
459
|
+
# top_system = $top_system
|
453
460
|
# Preprocess the HW description for valid C generation.
|
454
|
-
top_system.each_systemT_deep do |systemT|
|
461
|
+
$top_system.each_systemT_deep do |systemT|
|
455
462
|
# Converts the connections to behaviors.
|
456
463
|
systemT.connections_to_behaviors!
|
457
464
|
# Break the RefConcat.
|
@@ -463,10 +470,10 @@ elsif $options[:clang] then
|
|
463
470
|
if $options[:multiple] then
|
464
471
|
# Get the base name of the input file, it will be used for
|
465
472
|
# generating the main name of the multiple result files.
|
466
|
-
basename = File.basename($input,File.extname($input))
|
467
|
-
basename = $output + "/" + basename
|
468
|
-
# File name counter.
|
469
|
-
|
473
|
+
$basename = File.basename($input,File.extname($input))
|
474
|
+
$basename = $output + "/" + $basename
|
475
|
+
# # File name counter.
|
476
|
+
# $namecount = 0
|
470
477
|
|
471
478
|
# # Converts the connections to behaviors (C generation does not
|
472
479
|
# # support connections).
|
@@ -476,11 +483,11 @@ elsif $options[:clang] then
|
|
476
483
|
|
477
484
|
# Multiple files generation mode.
|
478
485
|
# Generate the h file.
|
479
|
-
hname = $output + "/hruby_sim_gen.h"
|
480
|
-
hnames = [ File.basename(hname) ]
|
481
|
-
outfile = File.open(hname,"w")
|
486
|
+
$hname = $output + "/hruby_sim_gen.h"
|
487
|
+
$hnames = [ File.basename($hname) ]
|
488
|
+
$outfile = File.open($hname,"w")
|
482
489
|
# Adds the generated globals
|
483
|
-
top_system.each_systemT_deep do |systemT|
|
490
|
+
$top_system.each_systemT_deep do |systemT|
|
484
491
|
# For the h file.
|
485
492
|
# hname = $output + "/" +
|
486
493
|
# HDLRuby::Low::Low2C.c_name(systemT.name) +
|
@@ -489,7 +496,7 @@ elsif $options[:clang] then
|
|
489
496
|
# # Open the file for current systemT
|
490
497
|
# output = File.open(hname,"w")
|
491
498
|
# Generate the H code in to.
|
492
|
-
outfile << systemT.to_ch
|
499
|
+
$outfile << systemT.to_ch
|
493
500
|
# # Close the file.
|
494
501
|
# output.close
|
495
502
|
# # Clears the name.
|
@@ -499,25 +506,25 @@ elsif $options[:clang] then
|
|
499
506
|
$non_hdlruby.each do |code|
|
500
507
|
code.each_chunk do |chunk|
|
501
508
|
if chunk.name == :sim then
|
502
|
-
outfile << "extern " +
|
509
|
+
$outfile << "extern " +
|
503
510
|
HDLRuby::Low::Low2C.prototype(chunk.to_c)
|
504
511
|
end
|
505
512
|
end
|
506
513
|
end
|
507
|
-
outfile.close
|
514
|
+
$outfile.close
|
508
515
|
|
509
516
|
# Prepare the initial name for the main file.
|
510
|
-
name = basename + ".c"
|
517
|
+
$name = $basename + ".c"
|
511
518
|
# Generate the code for it.
|
512
|
-
main = File.open(name,"w")
|
519
|
+
$main = File.open($name,"w")
|
513
520
|
|
514
521
|
# Generate the code of the main function.
|
515
522
|
# HDLRuby start code
|
516
|
-
main << HDLRuby::Low::Low2C.main(top_system,
|
517
|
-
top_system.each_systemT_deep.to_a.reverse
|
518
|
-
main.close
|
523
|
+
$main << HDLRuby::Low::Low2C.main($top_system,
|
524
|
+
$top_system.each_systemT_deep.to_a.reverse,$hnames)
|
525
|
+
$main.close
|
519
526
|
|
520
|
-
top_system.each_systemT_deep do |systemT|
|
527
|
+
$top_system.each_systemT_deep do |systemT|
|
521
528
|
# For the c file.
|
522
529
|
name = $output + "/" +
|
523
530
|
HDLRuby::Low::Low2C.c_name(systemT.name) +
|
@@ -525,7 +532,7 @@ elsif $options[:clang] then
|
|
525
532
|
# Open the file for current systemT
|
526
533
|
outfile = File.open(name,"w")
|
527
534
|
# Generate the C code in to.
|
528
|
-
outfile << systemT.to_c(0
|
535
|
+
outfile << systemT.to_c(0,*$hnames)
|
529
536
|
# Close the file.
|
530
537
|
outfile.close
|
531
538
|
# Clears the name.
|
@@ -533,7 +540,7 @@ elsif $options[:clang] then
|
|
533
540
|
end
|
534
541
|
else
|
535
542
|
# Single file generation mode.
|
536
|
-
top_system.each_systemT_deep.reverse_each do |systemT|
|
543
|
+
$top_system.each_systemT_deep.reverse_each do |systemT|
|
537
544
|
$output << systemT.to_ch
|
538
545
|
$output << systemT.to_c
|
539
546
|
end
|
@@ -545,12 +552,12 @@ elsif $options[:clang] then
|
|
545
552
|
# Simulation mode, compile and exectute.
|
546
553
|
# Path of the simulator core files.
|
547
554
|
# simdir = File.dirname(__FILE__) + "/sim/"
|
548
|
-
simdir = $hdr_dir + "/sim/"
|
555
|
+
$simdir = $hdr_dir + "/sim/"
|
549
556
|
# Generate and execute the simulation commands.
|
550
557
|
# Kernel.system("cp -n #{simdir}* #{$output}/; cd #{$output}/ ; make -s ; ./hruby_simulator")
|
551
|
-
Dir.entries(simdir).each do |filename|
|
558
|
+
Dir.entries($simdir).each do |filename|
|
552
559
|
if !File.directory?(filename) && /\.[ch]$/ === filename then
|
553
|
-
FileUtils.cp(simdir + "/" + filename,$output)
|
560
|
+
FileUtils.cp($simdir + "/" + filename,$output)
|
554
561
|
end
|
555
562
|
end
|
556
563
|
Dir.chdir($output)
|
@@ -561,9 +568,9 @@ elsif $options[:clang] then
|
|
561
568
|
elsif $options[:verilog] then
|
562
569
|
# warn("Verilog HDL output is not available yet... but it will be soon, promise!")
|
563
570
|
# top_system = $top_instance.to_low.systemT
|
564
|
-
top_system = $top_system
|
571
|
+
# top_system = $top_system
|
565
572
|
# Make description compatible with verilog generation.
|
566
|
-
top_system.each_systemT_deep do |systemT|
|
573
|
+
$top_system.each_systemT_deep do |systemT|
|
567
574
|
systemT.to_upper_space!
|
568
575
|
systemT.to_global_systemTs!
|
569
576
|
systemT.break_types!
|
@@ -575,28 +582,28 @@ elsif $options[:verilog] then
|
|
575
582
|
if $options[:multiple] then
|
576
583
|
# Get the base name of the input file, it will be used for
|
577
584
|
# generating the main name of the multiple result files.
|
578
|
-
basename = File.basename($input,File.extname($input))
|
579
|
-
basename = $output + "/" + basename
|
580
|
-
# File name counter.
|
581
|
-
|
585
|
+
$basename = File.basename($input,File.extname($input))
|
586
|
+
$basename = $output + "/" + $basename
|
587
|
+
# # File name counter.
|
588
|
+
# $namecount = 0
|
582
589
|
# Prepare the initial name for the main file.
|
583
|
-
name = basename + ".v"
|
590
|
+
$name = $basename + ".v"
|
584
591
|
# Multiple files generation mode.
|
585
|
-
top_system.each_systemT_deep do |systemT|
|
592
|
+
$top_system.each_systemT_deep do |systemT|
|
586
593
|
# Generate the name if necessary.
|
587
|
-
unless name
|
588
|
-
name = $output + "/" +
|
594
|
+
unless $name
|
595
|
+
$name = $output + "/" +
|
589
596
|
HDLRuby::Verilog.name_to_verilog(systemT.name) +
|
590
597
|
".v"
|
591
598
|
end
|
592
599
|
# Open the file for current systemT
|
593
|
-
outfile = File.open(name,"w")
|
594
|
-
# Generate the
|
600
|
+
outfile = File.open($name,"w")
|
601
|
+
# Generate the Verilog code in to.
|
595
602
|
outfile << systemT.to_verilog
|
596
603
|
# Close the file.
|
597
604
|
outfile.close
|
598
605
|
# Clears the name.
|
599
|
-
name = nil
|
606
|
+
$name = nil
|
600
607
|
end
|
601
608
|
else
|
602
609
|
# Single file generation mode.
|
@@ -606,9 +613,9 @@ elsif $options[:verilog] then
|
|
606
613
|
end
|
607
614
|
elsif $options[:vhdl] then
|
608
615
|
# top_system = $top_instance.to_low.systemT
|
609
|
-
top_system = $top_system
|
616
|
+
# top_system = $top_system
|
610
617
|
# Make description compatible with vhdl generation.
|
611
|
-
top_system.each_systemT_deep do |systemT|
|
618
|
+
$top_system.each_systemT_deep do |systemT|
|
612
619
|
systemT.outread2inner! unless $options[:vhdl08] || $options[:alliance]
|
613
620
|
systemT.with_boolean!
|
614
621
|
systemT.boolean_in_assign2select! unless $options[:alliance]
|
@@ -626,32 +633,32 @@ elsif $options[:vhdl] then
|
|
626
633
|
if $options[:multiple] then
|
627
634
|
# Get the base name of the input file, it will be used for
|
628
635
|
# generating the main name of the multiple result files.
|
629
|
-
basename = File.basename($input,File.extname($input))
|
630
|
-
basename = $output + "/" + basename
|
631
|
-
# File name counter.
|
632
|
-
|
636
|
+
$basename = File.basename($input,File.extname($input))
|
637
|
+
$basename = $output + "/" + $basename
|
638
|
+
# # File name counter.
|
639
|
+
# $namecount = 0
|
633
640
|
# Prepare the initial name for the main file.
|
634
|
-
name = basename + ".vhd"
|
641
|
+
$name = $basename + ".vhd"
|
635
642
|
# Multiple files generation mode.
|
636
|
-
top_system.each_systemT_deep do |systemT|
|
643
|
+
$top_system.each_systemT_deep do |systemT|
|
637
644
|
# Generate the name if necessary.
|
638
|
-
unless name
|
639
|
-
name = $output + "/" +
|
645
|
+
unless $name
|
646
|
+
$name = $output + "/" +
|
640
647
|
HDLRuby::Low::Low2VHDL.entity_name(systemT.name) +
|
641
648
|
".vhd"
|
642
649
|
end
|
643
650
|
# Open the file for current systemT
|
644
|
-
outfile = File.open(name,"w")
|
651
|
+
outfile = File.open($name,"w")
|
645
652
|
# Generate the VHDL code in to.
|
646
653
|
outfile << systemT.to_vhdl
|
647
654
|
# Close the file.
|
648
655
|
outfile.close
|
649
656
|
# Clears the name.
|
650
|
-
name = nil
|
657
|
+
$name = nil
|
651
658
|
end
|
652
659
|
else
|
653
660
|
# Single file generation mode.
|
654
|
-
top_system.each_systemT_deep.reverse_each do |systemT|
|
661
|
+
$top_system.each_systemT_deep.reverse_each do |systemT|
|
655
662
|
$output << systemT.to_vhdl
|
656
663
|
end
|
657
664
|
end
|