HDLRuby 2.3.1 → 2.3.6

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: bb0edfa902fbbc4e330f9a7fd8c26dcfc745f8ce5eb8cd73e4c2047cfef7dc68
4
- data.tar.gz: 5ddc2948c53b905fb25c0683fc31be5300a2aabff31384c9187dc784c9e66a76
3
+ metadata.gz: 78fe6b35a5069fd78646d2486c3d03dd00c5b24efa6a9710e3acc1248cc35145
4
+ data.tar.gz: c98bd555da00c6d2cffd9b5f41d48d5b8e4dd9584dc42e943934dc438fede8be
5
5
  SHA512:
6
- metadata.gz: 93f86b91bf94ad22b4558ac912f950e79ec9373fafcdcaf2d33e8f1c34f3b77d30beec308f591d95f7ddafdcfda5bd283586216a98c882e12983fbe7301f43df
7
- data.tar.gz: 60503ed5b5d45406827329bd6f42b961b9b6c74f47c630f7f0f21bd4d51bcbabffb380608c2287ee7dd8b60b5bb2039eaddd82357920eff3f6b437b40d59d34a
6
+ metadata.gz: 48acf3975e6f9d36b0257ad165b407ed27d949b61793a1628e983c793163668c0c09b2c734cf41c44343ad55f7195c3fc60eb168b9de18dac82e5ecd6f1c6d17
7
+ data.tar.gz: 7b028598447ab6bd940a077b184eb7bd27524e157185cb97ef28e25eb4760e187d8d7f0ea1fada54b549f6bd4bc6baf38706efe2505f6cfd26c215e6bce91955
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,29 @@ 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).inner :readL0
26
+ # # memL1.branch(:rinc).inner :readL1
27
+ # # memR.branch(:rinc).inner :readR
28
+ # memL0.branch(:rinc).input :readL0
29
+ # memL1.branch(:rinc).input :readL1
30
+ # memR.branch(:rinc).input :readR
28
31
 
29
32
  # Prepares the left and acc arrays.
30
- lefts = [readL0, readL1]
33
+ # lefts = [readL0, readL1]
34
+ lefts = [memL0.branch(:rinc), memL1.branch(:rinc)]
31
35
 
32
36
  # Accumulators memory.
33
37
  mem_file([8],2,clk,rst,rinc: :rst).(:memAcc)
34
- memAcc.branch(:anum).inner :accs
38
+ # # memAcc.branch(:anum).inner :accs
39
+ memAcc.branch(:anum).inout :accs
35
40
  accs_out = [accs.wrap(0), accs.wrap(1)]
36
41
 
37
42
  # Layer 0 ack.
38
43
  inner :ack0
39
44
 
40
45
  # Instantiate the matrix product.
41
- mac_n1([8],clk,req,ack0,lefts,readR,accs_out)
46
+ # mac_n1([8],clk,req,ack0,lefts,readR,accs_out)
47
+ mac_n1([8],clk,req,ack0,lefts,memR.branch(:rinc),accs_out)
42
48
 
43
49
  # Translation.
44
50
  # Translation memory.
@@ -46,10 +52,12 @@ system :testmat do
46
52
  # Tarnslation result
47
53
  mem_file([8],2,clk,rst,rinc: :rst).(:memF)
48
54
  # Access ports.
49
- memT.branch(:anum).inner :readT
50
- memF.branch(:anum).inner :writeF
55
+ # # memT.branch(:anum).inner :readT
56
+ # # memF.branch(:anum).inner :writeF
57
+ memT.branch(:anum).input :readT
58
+ memF.branch(:anum).output :writeF
51
59
  regRs = [ readT.wrap(0), readT.wrap(1) ]
52
- regLs = [ accs.wrap(0), accs.wrap(1) ]
60
+ regLs = accs_out
53
61
  regs = [ writeF.wrap(0), writeF.wrap(1) ]
54
62
 
55
63
  # Translater ack.
@@ -64,9 +72,10 @@ system :testmat do
64
72
  # Input memories.
65
73
  mem_dual([8],2,clk,rst, rinc: :rst,winc: :rst).(:mem2L0)
66
74
  # Access ports.
67
- mem2L0.branch(:rinc).inner :read2L0
68
- # memAcc.branch(:rinc).inner :accsR
69
- memF.branch(:rinc).inner :readF
75
+ # # mem2L0.branch(:rinc).inner :read2L0
76
+ # # memF.branch(:rinc).inner :readF
77
+ # mem2L0.branch(:rinc).input :read2L0
78
+ # memF.branch(:rinc).input :readF
70
79
 
71
80
  # Second layer ack.
72
81
  inner :ack1
@@ -76,29 +85,40 @@ system :testmat do
76
85
 
77
86
  sub do
78
87
  # Instantiate the second matrix product.
79
- # mac([8],clk,req,read2L0,accsR,res)
80
- mac([8],clk,ackT,ack1,read2L0,readF,channel_port(res))
88
+ # mac([8],clk,ackT,ack1,read2L0,readF,channel_port(res))
89
+ mac([8],clk,ackT,ack1,mem2L0.branch(:rinc),memF.branch(:rinc),
90
+ channel_port(res))
81
91
  end
82
92
 
83
93
 
84
94
 
85
95
  # 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
96
+ # # memL0.branch(:winc).inner :writeL0
97
+ # # memL1.branch(:winc).inner :writeL1
98
+ # # memR.branch(:winc).inner :writeR
99
+ # # memT.branch(:winc).inner :writeT
100
+ # # mem2L0.branch(:winc).inner :write2L0
101
+ # memL0.branch(:winc).output :writeL0
102
+ # memL1.branch(:winc).output :writeL1
103
+ # memR.branch(:winc).output :writeR
104
+ # mem2L0.branch(:winc).output :write2L0
105
+ # memT.branch(:winc).output :writeT
91
106
  inner :fill, :fill2
92
107
  [8].inner :val
93
108
  par(clk.posedge) do
94
109
  hif(fill) do
95
- writeL0.write(val)
96
- writeL1.write(val+1)
97
- writeR.write(val+1)
110
+ # writeL0.write(val)
111
+ # writeL1.write(val+1)
112
+ # writeR.write(val+1)
113
+ memL0.branch(:winc).write(val)
114
+ memL1.branch(:winc).write(val+1)
115
+ memR.branch(:winc).write(val+1)
98
116
  end
99
117
  hif(fill2) do
100
- write2L0.write(val+2)
101
- writeT.write(val+2)
118
+ # write2L0.write(val+2)
119
+ # writeT.write(val+2)
120
+ mem2L0.branch(:winc).write(val+2)
121
+ memT.branch(:winc).write(val+2)
102
122
  end
103
123
  end
104
124
 
@@ -113,12 +113,9 @@ module HDLRuby
113
113
  return
114
114
  end
115
115
  # Get its required files.
116
- requires = @checks[-1].get_all_requires
116
+ requires = @checks[-1].get_all_requires +
117
+ @checks[-1].get_all_require_relatives
117
118
  requires.each do |file|
118
- # if file != "HDLRuby" &&
119
- # !@std_files.find { |std| std.include?(file) } then
120
- # read_all(file)
121
- # end
122
119
  read_all(file)
123
120
  end
124
121
  @requires += requires
@@ -244,7 +241,7 @@ include HDLRuby
244
241
  # Process the command line options
245
242
  $options = {}
246
243
  $optparse = OptionParser.new do |opts|
247
- opts.banner = "Usage: hdrcc.rb [options] <input file> [<output file>]"
244
+ opts.banner = "Usage: hdrcc.rb [options] <input file> [<output directory or file>]"
248
245
 
249
246
  opts.separator ""
250
247
  opts.separator "Where:"
@@ -326,18 +323,17 @@ $optparse = OptionParser.new do |opts|
326
323
  opts.separator ""
327
324
  opts.separator "Notice:"
328
325
  opts.separator "* If no output option is given, simply checks the input file"
329
- opts.separator "* If no output file is given, the result is given through the standard output."
330
326
  opts.separator "* If no top system is given, it will be automatically searched in the input file."
331
327
  opts.separator ""
332
328
  opts.separator "Examples:"
333
329
  opts.separator "* Compile system named `adder` from `adder.rb` input file and generate `adder.yaml` low-level YAML description:"
334
330
  opts.separator " hdrcc.rb --yaml --top adder adder.rb adder.yaml"
335
- opts.separator "* Compile `adder.rb` input file and generate `adder.vhd` low-level VHDL description:"
336
- 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"
337
333
  opts.separator "* Check the validity of `adder.rb` input file:"
338
334
  opts.separator " hdrcc.rb adder.rb"
339
- 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:"
340
- 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"
341
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`"
342
338
  opts.separator "hdrcc -y -t multer -p 16,16,32 multer_gen.rb multer_gen.yaml"
343
339
 
@@ -45,11 +45,20 @@ module HDLRuby
45
45
  (code[1][1] == "require")
46
46
  end
47
47
 
48
+ # Tells if +code+ is require_relative description.
49
+ def is_require_relative?(code)
50
+ # return code[0] && (code[0][0] == :command) &&
51
+ # (code[0][1][1] == "require_relative")
52
+ return code && (code[0] == :command) &&
53
+ (code[1][1] == "require_relative")
54
+ end
55
+
48
56
  # Gets the required file from +code+.
49
57
  def get_require(code)
50
58
  # return (code[0][2][1][0][1][1][1])
51
59
  return (code[2][1][0][1][1][1])
52
60
  end
61
+ alias_method :get_require_relative, :get_require
53
62
 
54
63
  # Gets all the required files of +code+.
55
64
  def get_all_requires(code = @code)
@@ -66,6 +75,21 @@ module HDLRuby
66
75
  end
67
76
  end
68
77
 
78
+ # Gets all the require_relative files of +code+.
79
+ def get_all_require_relatives(code = @code)
80
+ if code.is_a?(Array) then
81
+ require_relatives = (code.select { |sub| is_require_relative?(sub) }).map! do |sub|
82
+ get_require_relative(sub)
83
+ end
84
+ code.each do |sub|
85
+ require_relatives += get_all_require_relatives(sub)
86
+ end
87
+ return require_relatives
88
+ else
89
+ return []
90
+ end
91
+ end
92
+
69
93
  # Tells if +code+ is a system description.
70
94
  def is_system?(code)
71
95
  return code.is_a?(Array) && (code[0] == :command) &&
@@ -77,7 +101,7 @@ module HDLRuby
77
101
  return code[2][1][0][1][1][1]
78
102
  end
79
103
 
80
- # Gets all the required files of +code+.
104
+ # Gets all the systems of +code+.
81
105
  def get_all_systems(code = @code)
82
106
  return [] unless code.is_a?(Array)
83
107
  return code.reduce([]) {|ar,sub| ar + get_all_systems(sub) } +
@@ -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