HDLRuby 2.3.2 → 2.3.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73fbfcef7b930ac266b56380159ffd3af64f84ce712f937f764559d8abe78ded
4
- data.tar.gz: 2c7ad1ac7fac5639f70278f28dce24cdfa4328797b2b031f698421a849ee5141
3
+ metadata.gz: bb0dfd0d3f5fd062cd7e31f46eab82f0090e58eb8690a50a74106cfa32b5b9c2
4
+ data.tar.gz: 46f437035c02b4c8de14fb5033361b2d65cb6a7916887ca16a1dea67adadc8b9
5
5
  SHA512:
6
- metadata.gz: 4112497c5716f1dd13ae9f45a4806773ae7f521b586415c2b0be4a735357765a45c2f524d33bff509f0dfc103ed47fc3aceee19e7eea98ec8d0c720d88af3153
7
- data.tar.gz: 1852065b8f05fb474f6f392df45cf08269196f2f481a55d84d1a5d20ad66713a5138eb739e0146ce1761fe3f22eccb01bcea06d19e94a19b3693a01dbba4e165
6
+ metadata.gz: f6db11e75542e9b1f3e9064c32b3d8979ff3815ff661bfe8defc80f9625b671851a341366ad021a120305071e5f2099f95193e8a2332366460b967c6755a041f
7
+ data.tar.gz: 44a91392735fa86edc102ae6d20aa54dd85628e2efac5f4112731d2733bf7b555e4dce9bc39a086efbb5c3a1f1f0d2a4bb0e420be1f6251d26a505599bff526d
data/README.md CHANGED
@@ -2815,27 +2815,17 @@ This library provides a unified interface to complex communication protocols thr
2815
2815
  ### Using a channel
2816
2816
 
2817
2817
  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:
2818
-
2819
- * `input <name>`: generate ports in the system for reading from the channel amd associate them to `name`
2820
- * `output <name>`: generate ports in the system for writing to the channel and associate them to `name`
2821
- * `inout <name>`: generate ports in the system for reading and writing to the channel and associate them to `name`
2822
- * `inner <name>`: generates inner signals for accessing directly the channel
2823
-
2824
- __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.
2825
-
2826
- When the channel ports are declared, they can be accessed using the following methods depending on whether they are writing or reading ports:
2827
2818
 
2828
2819
  * `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.
2829
2820
  * `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.
2830
2821
 
2822
+
2831
2823
  For example, a system sending successive 8-bit values through a channel can be described as follows:
2832
2824
 
2833
2825
  ```ruby
2834
2826
  system :producer8 do |channel|
2835
2827
  # Inputs of the producer: clock and reset.
2836
2828
  input :clk, :rst
2837
- # Instantiate the channel ports
2838
- channel.output :chi
2839
2829
  # Inner 8-bit counter for generating values.
2840
2830
  [8].inner :counter
2841
2831
 
@@ -2843,7 +2833,7 @@ system :producer8 do |channel|
2843
2833
  par(clk.posedge) do
2844
2834
  hif(rst) { counter <= 0 }
2845
2835
  helse do
2846
- chi.write(counter) { counter <= counter + 1 }
2836
+ channel.write(counter) { counter <= counter + 1 }
2847
2837
  end
2848
2838
  end
2849
2839
  end
@@ -2851,6 +2841,22 @@ end
2851
2841
 
2852
2842
  __Note__: In the code above, the channel is passed as generic argument of the system.
2853
2843
 
2844
+ The access points to a channel can also be handled individually by declaring ports using the following methods:
2845
+
2846
+ * `input <name>`: declares a port for reading from the channel and associate them to `name` if any
2847
+ * `output <name>`: declares a port for writing to the channel and associate them to `name` if any
2848
+ * `inout <name>`: declares a port for reading and writing to the channel and associate them to `name` if any
2849
+
2850
+ Such port can then be accessed using the same `read` and `write` method of a channel, the difference being that they can also be configured for new access procedure using the `wrap` method:
2851
+
2852
+ * `wrap(<args>) <code>`: creates a new port whose read or write procedure has the elements of `<args>` and the ones produced by `<code>` assign to the arguments of the read or write procedure.
2853
+
2854
+ For example, assuming `mem` is a channel whose read and write access have as argument the target address and data signals, the following code creates a port for always accessing at address 0:
2855
+
2856
+ ```ruby
2857
+ addr0 = channel.input.wrap(0)
2858
+ ```
2859
+
2854
2860
  ### Channel branches
2855
2861
 
2856
2862
  Some channel may include several branches, they are accessed by name using the following method:
@@ -2894,7 +2900,7 @@ Where `name` is the name of the channel and `block` is a procedure block describ
2894
2900
  The first argument of the block must be the following:
2895
2901
  - `blk`: the block to execute when the write completes.
2896
2902
  Other arguments can be freely defined, and will be required by the `write` command.
2897
- * `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.
2903
+ * `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 possibility to access the internals of the upper channel.
2898
2904
 
2899
2905
  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:
2900
2906
 
@@ -63,12 +63,13 @@ end
63
63
 
64
64
 
65
65
  # A system writing indefinitely to a channel.
66
+ # Checking usage of channel without declaring a port.
66
67
  system :producer8 do |channel|
67
- # puts "channel=#{channel}"
68
+ # puts "channel=#{channel}, channel methods=#{channel.methods}"
68
69
  # Inputs of the producer: clock and reset.
69
70
  input :clk, :rst
70
- # Instantiate the channel ports
71
- channel.output :ch
71
+ # # Instantiate the channel ports
72
+ # channel.output :ch
72
73
  # Inner 8-bit counter for generating values.
73
74
  [8].inner :counter
74
75
 
@@ -76,7 +77,8 @@ system :producer8 do |channel|
76
77
  par(clk.posedge) do
77
78
  hif(rst) { counter <= 0 }
78
79
  helse do
79
- ch.write(counter) { counter <= counter + 1 }
80
+ # ch.write(counter) { counter <= counter + 1 }
81
+ channel.write(counter) { counter <= counter + 1 }
80
82
  end
81
83
  end
82
84
  end
@@ -96,20 +98,59 @@ system :consummer8 do |channel|
96
98
  end
97
99
  end
98
100
 
101
+ # A system reading indefinitely from a channel.
102
+ # Version without port declaration.
103
+ system :consummer16 do |channel|
104
+ # Input of the consummer: a clock is enough.
105
+ input :clk
106
+ # # Instantiate the channel ports
107
+ # channel.input :ch
108
+ # Inner buffer for storing the cunsummed value.
109
+ [16].inner :buf
110
+
111
+ # The value consumption process
112
+ par(clk.posedge) do
113
+ # ch.read(buf)
114
+ channel.read(buf)
115
+ end
116
+ end
117
+
99
118
 
100
119
  # A system testing the handshaker.
101
120
  system :hs_test do
102
121
  input :clk,:rst
103
122
 
104
- # Declares the handshaker
105
- handshaker([8]).(:hs)
123
+ # Declares two handshakers
124
+ handshaker([8]).(:hs0)
125
+ handshaker([16]).(:hs1)
106
126
 
107
127
  # # Sets the reset.
108
128
  # par(rst.posedge) { hs.reset }
129
+
130
+ # For the first handshake
109
131
 
110
132
  # Instantiate the producer.
111
- producer8(hs).(:producerI).(clk,rst)
133
+ producer8(hs0).(:producerI).(clk,rst)
112
134
 
113
135
  # Instantiate the consummer.
114
- consummer8(hs).(:consummerI).(clk)
136
+ consummer8(hs0).(:consummerI).(clk)
137
+
138
+ # For the second handshaker
139
+
140
+ # Instantiatethe consummer.
141
+ consummer16(hs1).(:consummer2I).(clk)
142
+
143
+ # Produce from within.
144
+ [16].inner :counter
145
+
146
+ # hs1.output :port
147
+
148
+ par(clk.posedge) do
149
+ hif(rst) { counter <= 0 }
150
+ helse do
151
+ # port.write(counter) { counter <= counter + 1 }
152
+ hs1.write(counter) { counter <= counter + 1 }
153
+ end
154
+ end
155
+
115
156
  end
@@ -22,23 +22,26 @@ system :testmat do
22
22
  mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL1)
23
23
  mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memR)
24
24
  # Access ports.
25
- memL0.branch(:rinc).inner :readL0
26
- memL1.branch(:rinc).inner :readL1
27
- memR.branch(:rinc).inner :readR
25
+ # memL0.branch(:rinc).input :readL0
26
+ # memL1.branch(:rinc).input :readL1
27
+ # memR.branch(:rinc).input :readR
28
28
 
29
29
  # Prepares the left and acc arrays.
30
- lefts = [readL0, readL1]
30
+ # lefts = [readL0, readL1]
31
+ lefts = [memL0.branch(:rinc), memL1.branch(:rinc)]
31
32
 
32
33
  # Accumulators memory.
33
34
  mem_file([8],2,clk,rst,rinc: :rst).(:memAcc)
34
- memAcc.branch(:anum).inner :accs
35
- accs_out = [accs.wrap(0), accs.wrap(1)]
35
+ # memAcc.branch(:anum).inout :accs
36
+ # accs_out = [accs.wrap(0), accs.wrap(1)]
37
+ accs_out = [memAcc.branch(:anum).wrap(0), memAcc.branch(:anum).wrap(1)]
36
38
 
37
39
  # Layer 0 ack.
38
40
  inner :ack0
39
41
 
40
42
  # Instantiate the matrix product.
41
- mac_n1([8],clk,req,ack0,lefts,readR,accs_out)
43
+ # mac_n1([8],clk,req,ack0,lefts,readR,accs_out)
44
+ mac_n1([8],clk,req,ack0,lefts,memR.branch(:rinc),accs_out)
42
45
 
43
46
  # Translation.
44
47
  # Translation memory.
@@ -46,10 +49,10 @@ system :testmat do
46
49
  # Tarnslation result
47
50
  mem_file([8],2,clk,rst,rinc: :rst).(:memF)
48
51
  # Access ports.
49
- memT.branch(:anum).inner :readT
50
- memF.branch(:anum).inner :writeF
52
+ memT.branch(:anum).input :readT
53
+ memF.branch(:anum).output :writeF
51
54
  regRs = [ readT.wrap(0), readT.wrap(1) ]
52
- regLs = [ accs.wrap(0), accs.wrap(1) ]
55
+ regLs = accs_out
53
56
  regs = [ writeF.wrap(0), writeF.wrap(1) ]
54
57
 
55
58
  # Translater ack.
@@ -64,9 +67,8 @@ system :testmat do
64
67
  # Input memories.
65
68
  mem_dual([8],2,clk,rst, rinc: :rst,winc: :rst).(:mem2L0)
66
69
  # Access ports.
67
- mem2L0.branch(:rinc).inner :read2L0
68
- # memAcc.branch(:rinc).inner :accsR
69
- memF.branch(:rinc).inner :readF
70
+ # mem2L0.branch(:rinc).input :read2L0
71
+ # memF.branch(:rinc).input :readF
70
72
 
71
73
  # Second layer ack.
72
74
  inner :ack1
@@ -76,29 +78,35 @@ system :testmat do
76
78
 
77
79
  sub do
78
80
  # Instantiate the second matrix product.
79
- # mac([8],clk,req,read2L0,accsR,res)
80
- mac([8],clk,ackT,ack1,read2L0,readF,channel_port(res))
81
+ # mac([8],clk,ackT,ack1,read2L0,readF,channel_port(res))
82
+ mac([8],clk,ackT,ack1,mem2L0.branch(:rinc),memF.branch(:rinc),
83
+ channel_port(res))
81
84
  end
82
85
 
83
86
 
84
87
 
85
88
  # The memory initializer.
86
- memL0.branch(:winc).inner :writeL0
87
- memL1.branch(:winc).inner :writeL1
88
- memR.branch(:winc).inner :writeR
89
- memT.branch(:winc).inner :writeT
90
- mem2L0.branch(:winc).inner :write2L0
89
+ # memL0.branch(:winc).output :writeL0
90
+ # memL1.branch(:winc).output :writeL1
91
+ # memR.branch(:winc).output :writeR
92
+ # mem2L0.branch(:winc).output :write2L0
93
+ # memT.branch(:winc).output :writeT
91
94
  inner :fill, :fill2
92
95
  [8].inner :val
93
96
  par(clk.posedge) do
94
97
  hif(fill) do
95
- writeL0.write(val)
96
- writeL1.write(val+1)
97
- writeR.write(val+1)
98
+ # writeL0.write(val)
99
+ # writeL1.write(val+1)
100
+ # writeR.write(val+1)
101
+ memL0.branch(:winc).write(val)
102
+ memL1.branch(:winc).write(val+1)
103
+ memR.branch(:winc).write(val+1)
98
104
  end
99
105
  hif(fill2) do
100
- write2L0.write(val+2)
101
- writeT.write(val+2)
106
+ # write2L0.write(val+2)
107
+ # writeT.write(val+2)
108
+ mem2L0.branch(:winc).write(val+2)
109
+ memT.branch(:winc).write(val+2)
102
110
  end
103
111
  end
104
112
 
@@ -241,7 +241,7 @@ include HDLRuby
241
241
  # Process the command line options
242
242
  $options = {}
243
243
  $optparse = OptionParser.new do |opts|
244
- opts.banner = "Usage: hdrcc.rb [options] <input file> [<output file>]"
244
+ opts.banner = "Usage: hdrcc.rb [options] <input file> [<output directory or file>]"
245
245
 
246
246
  opts.separator ""
247
247
  opts.separator "Where:"
@@ -323,18 +323,17 @@ $optparse = OptionParser.new do |opts|
323
323
  opts.separator ""
324
324
  opts.separator "Notice:"
325
325
  opts.separator "* If no output option is given, simply checks the input file"
326
- opts.separator "* If no output file is given, the result is given through the standard output."
327
326
  opts.separator "* If no top system is given, it will be automatically searched in the input file."
328
327
  opts.separator ""
329
328
  opts.separator "Examples:"
330
329
  opts.separator "* Compile system named `adder` from `adder.rb` input file and generate `adder.yaml` low-level YAML description:"
331
330
  opts.separator " hdrcc.rb --yaml --top adder adder.rb adder.yaml"
332
- opts.separator "* Compile `adder.rb` input file and generate `adder.vhd` low-level VHDL description:"
333
- opts.separator " hdrcc.rb --vhdl adder.rb adder.vhd"
331
+ opts.separator "* Compile `adder.rb` input file and generate low-level VHDL description files in `adder_vhd` directory:"
332
+ opts.separator " hdrcc.rb --vhdl adder.rb adder_vhd"
334
333
  opts.separator "* Check the validity of `adder.rb` input file:"
335
334
  opts.separator " hdrcc.rb adder.rb"
336
- opts.separator "* Compile system `adder` whose bit width is generic from `adder_gen.rb` input file to a 16-bit circuit whose low-level Verilog HDL description is dumped to the standard output:"
337
- opts.separator " hdrcc -v -t adder --param 16 adder_gen.rb"
335
+ opts.separator "* Compile system `adder` whose bit width is generic from `adder_gen.rb` input file to a 16-bit circuit whose low-level Verilog HDL description files are put in `adder_gen_v` directory:"
336
+ opts.separator " hdrcc -v -t adder --param 16 adder_gen.rb adder_gen_v"
338
337
  opts.separator "* Compile system `multer` with inputs and output bit width is generic from `multer_gen.rb` input file to a 16x16->32 bit cicruit whose low-level YAML description is saved to output file `multer_gen.yaml`"
339
338
  opts.separator "hdrcc -y -t multer -p 16,16,32 multer_gen.rb multer_gen.yaml"
340
339
 
@@ -1263,7 +1263,8 @@ module HDLRuby::High
1263
1263
  # Converts the scope to HDLRuby::Low.
1264
1264
  def to_low()
1265
1265
  # Create the resulting low scope.
1266
- scopeLow = HDLRuby::Low::Scope.new()
1266
+ # scopeLow = HDLRuby::Low::Scope.new()
1267
+ scopeLow = HDLRuby::Low::Scope.new(self.name)
1267
1268
  # Push the private namespace for the low generation.
1268
1269
  High.space_push(@namespace)
1269
1270
  # Pushes on the name stack for converting the internals of
@@ -1858,7 +1859,8 @@ module HDLRuby::High
1858
1859
  def function(name, &ruby_block)
1859
1860
  if HDLRuby::High.in_system? then
1860
1861
  define_singleton_method(name.to_sym) do |*args,&other_block|
1861
- sub do
1862
+ # sub do
1863
+ sub(HDLRuby.uniq_name(name)) do
1862
1864
  HDLRuby::High.top_user.instance_exec(*args,*other_block,
1863
1865
  &ruby_block)
1864
1866
  # ruby_block.call(*args)
@@ -1866,7 +1868,8 @@ module HDLRuby::High
1866
1868
  end
1867
1869
  else
1868
1870
  define_method(name.to_sym) do |*args,&other_block|
1869
- sub do
1871
+ # sub do
1872
+ sub(HDLRuby.uniq_name(name)) do
1870
1873
  HDLRuby::High.top_user.instance_exec(*args,*other_block,
1871
1874
  &ruby_block)
1872
1875
  end
@@ -1123,6 +1123,10 @@ module HDLRuby::Low
1123
1123
  return self.parent.is_a?(SystemT) ? self : self.parent.top_scope
1124
1124
  end
1125
1125
 
1126
+ # Gets the parent system, i.e., the parent of the top scope.
1127
+ def parent_system
1128
+ return self.top_scope.parent
1129
+ end
1126
1130
 
1127
1131
  end
1128
1132
 
@@ -2132,6 +2136,11 @@ module HDLRuby::Low
2132
2136
  def top_scope
2133
2137
  return parent.top_scope
2134
2138
  end
2139
+
2140
+ # Gets the parent system, i.e., the parent of the top scope.
2141
+ def parent_system
2142
+ return self.top_scope.parent
2143
+ end
2135
2144
  end
2136
2145
 
2137
2146
 
@@ -2619,6 +2628,11 @@ module HDLRuby::Low
2619
2628
  def top_scope
2620
2629
  return self.scope.top_scope
2621
2630
  end
2631
+
2632
+ # Gets the parent system, i.e., the parent of the top scope.
2633
+ def parent_system
2634
+ return self.top_scope.parent
2635
+ end
2622
2636
  end
2623
2637
 
2624
2638
 
@@ -3717,6 +3731,11 @@ module HDLRuby::Low
3717
3731
  def top_scope
3718
3732
  return self.parent.is_a?(Scope) ? self.parent : self.parent.top_scope
3719
3733
  end
3734
+
3735
+ # Gets the parent system, i.e., the parent of the top scope.
3736
+ def parent_system
3737
+ return self.top_scope.parent
3738
+ end
3720
3739
  end
3721
3740
 
3722
3741
 
@@ -1946,7 +1946,9 @@ module HDLRuby::Low
1946
1946
  # Generates the C text for reference as left value to a signal.
1947
1947
  # +level+ is the hierarchical level of the object.
1948
1948
  def to_c_signal(level = 0)
1949
- return to_c(level,true)
1949
+ # return to_c(level,true)
1950
+ return "make_ref_rangeS(#{self.ref.to_c_signal(level)}," +
1951
+ "value2integer(#{self.range.first.to_c(level)}),value2integer(#{self.range.last.to_c(level)}))"
1950
1952
  end
1951
1953
  end
1952
1954
 
@@ -29,6 +29,7 @@ module HDLRuby::Low
29
29
  if scope.each_connection.to_a.any? then
30
30
  inputs_blk = Block.new(:par)
31
31
  outputs_blk = Block.new(:par)
32
+ timed_blk = TimeBlock.new(:seq)
32
33
  scope.each_connection do |connection|
33
34
  # Check the left and right of the connection
34
35
  # for input or output port.
@@ -40,6 +41,15 @@ module HDLRuby::Low
40
41
  right_r = right.resolve if right.respond_to?(:resolve)
41
42
  # puts "right_r=#{right_r.name}" if right_r
42
43
  # puts "right_r.parent=#{right_r.parent.name}" if right_r && right_r.parent
44
+ if right.is_a?(Value) then
45
+ # Right is value, the new transmit is to add
46
+ # to the timed block.
47
+ timed_blk.add_statement(
48
+ Transmit.new(left.clone,right.clone))
49
+ # No more process for this connection.
50
+ next
51
+ end
52
+
43
53
  # Check if left is an input or an output.
44
54
  left_is_i = left_is_o = false
45
55
  if left_r && left_r.parent.is_a?(SystemT) then
@@ -118,6 +128,9 @@ module HDLRuby::Low
118
128
  if outputs_blk.each_statement.any? then
119
129
  scope.add_behavior(Behavior.new(outputs_blk))
120
130
  end
131
+ if timed_blk.each_statement.any? then
132
+ scope.add_behavior(TimeBehavior.new(timed_blk))
133
+ end
121
134
  end
122
135
  end
123
136
  end
@@ -13,9 +13,9 @@ module HDLRuby
13
13
  @@absoluteCounter = -1 # The absolute name counter.
14
14
 
15
15
  # Generates an absolute uniq name.
16
- def self.uniq_name
16
+ def self.uniq_name(base = "")
17
17
  @@absoluteCounter += 1
18
- name = ":#{@@absoluteCounter}"
18
+ name = base.to_s + ":#{@@absoluteCounter}"
19
19
  if Symbol.all_symbols.find {|symbol| symbol.to_s == name } then
20
20
  # The symbol exists, try again.
21
21
  return self.uniq_name
@@ -612,14 +612,18 @@ extern Value read_range(Value value, long long first, long long last,
612
612
  * @param src the source value
613
613
  * @param first the first index of the range
614
614
  * @param last the last index of the range
615
+ * @param base the type of the elements
615
616
  * @param dst the destination value
616
617
  * @return dst */
617
- extern Value write_range(Value src, long long first, long long last, Value dst);
618
+ extern Value write_range(Value src, long long first, long long last,
619
+ Type base, Value dst);
618
620
 
619
621
  /** Writes to a range within a value but without overwrite with Z.
620
622
  * @param src the source value
621
623
  * @param first the first index of the range
622
624
  * @param last the last index of the range
625
+ * @param base the type of the elements
623
626
  * @param dst the destination value
624
627
  * @return dst */
625
- extern Value write_range_no_z(Value src, long long first, long long last, Value dst);
628
+ extern Value write_range_no_z(Value src, long long first, long long last,
629
+ Type base, Value dst);