HDLRuby 2.3.2 → 2.3.3

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: 6548ba8f8c1572f8aa254b168eab065bc5d0a06ac996d792b4082a9243a2dfc9
4
+ data.tar.gz: 97891dad52f2454d37755af82cf6d23b2665cccd39a44caff81701921f233931
5
5
  SHA512:
6
- metadata.gz: 4112497c5716f1dd13ae9f45a4806773ae7f521b586415c2b0be4a735357765a45c2f524d33bff509f0dfc103ed47fc3aceee19e7eea98ec8d0c720d88af3153
7
- data.tar.gz: 1852065b8f05fb474f6f392df45cf08269196f2f481a55d84d1a5d20ad66713a5138eb739e0146ce1761fe3f22eccb01bcea06d19e94a19b3693a01dbba4e165
6
+ metadata.gz: 6df258eebc8a3448824aca9bf39d24ad98c9302728c2584bb34880b8160b42a00f6b7e0fed68a4097403046e0621bf16c8048c43ce95090254f4e9e6e1ebc079
7
+ data.tar.gz: 73cc373d53e91a756922c8539f15283f793db0ce6e1b3e7c2ae566ae6e2c19691ee62d7dd3ac5ca1f1e19c61a809ab234aba3c790ae207327f8cd2609c76816f
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
 
@@ -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
 
@@ -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
 
@@ -365,6 +365,7 @@ void* behavior_run(void* arg) {
365
365
  * @note create a thread per timed behavior. */
366
366
  void hruby_sim_start_timed_behaviors() {
367
367
  int i;
368
+ pthread_mutex_lock(&hruby_sim_mutex);
368
369
  /* Sets the end flags to 0. */
369
370
  sim_end_flag = 0;
370
371
  /* Create and start the threads. */
@@ -375,6 +376,7 @@ void hruby_sim_start_timed_behaviors() {
375
376
  pthread_create(&timed_behaviors[i]->thread,NULL,
376
377
  &behavior_run,timed_behaviors[i]);
377
378
  }
379
+ pthread_mutex_unlock(&hruby_sim_mutex);
378
380
  }
379
381
 
380
382
  /** Ends waiting all the threads properly terminates. */
@@ -96,6 +96,9 @@ module HDLRuby::High::Std
96
96
  def wrap(*args)
97
97
  return ChannelPortB.new(self,*args)
98
98
  end
99
+
100
+ # The scope the port has been declared in.
101
+ attr_reader :scope
99
102
  end
100
103
 
101
104
 
@@ -113,6 +116,7 @@ module HDLRuby::High::Std
113
116
  @namespace = namespace
114
117
  @reader_proc = reader_proc.to_proc
115
118
  @rester_proc = reseter_proc ? reseter_proc.to_proc : proc {}
119
+ @scope = HDLRuby::High.cur_scope
116
120
  end
117
121
 
118
122
  ## Performs a read on the channel using +args+ and +ruby_block+
@@ -157,6 +161,7 @@ module HDLRuby::High::Std
157
161
  @namespace = namespace
158
162
  @writer_proc = writer_proc.to_proc
159
163
  @reseter_proc = reseter_proc ? reseter_proc.to_proc : proc {}
164
+ @scope = HDLRuby::High.cur_scope
160
165
  end
161
166
 
162
167
  ## Performs a write on the channel using +args+ and +ruby_block+
@@ -206,6 +211,7 @@ module HDLRuby::High::Std
206
211
  @reader_proc = reader_proc ? reader_proc.to_proc : proc { }
207
212
  @writer_proc = writer_proc ? writer_proc.to_proc : proc { }
208
213
  @reseter_proc = reseter_proc ? reseter_proc.to_proc : proc {}
214
+ @scope = HDLRuby::High.cur_scope
209
215
  end
210
216
 
211
217
  ## Performs a read on the channel using +args+ and +ruby_block+
@@ -281,6 +287,8 @@ module HDLRuby::High::Std
281
287
  @args_write = args.clone
282
288
  @args_access = args.clone
283
289
  end
290
+
291
+ @scope = @port.scope
284
292
  end
285
293
 
286
294
  ## Performs a read on the channel using +args+ and +ruby_block+
@@ -332,6 +340,12 @@ module HDLRuby::High::Std
332
340
  # building a channel.
333
341
  attr_reader :namespace
334
342
 
343
+ # The read port if any.
344
+ attr_reader :read_port
345
+
346
+ # The write port if any.
347
+ attr_reader :write_port
348
+
335
349
  ## Creates a new channel instance with +name+ built from +ruby_block+.
336
350
  def initialize(name,&ruby_block)
337
351
  # Check and set the name of the channel.
@@ -346,6 +360,10 @@ module HDLRuby::High::Std
346
360
  # Keep access to self.
347
361
  obj = self
348
362
 
363
+ # At first there no read nor write port.
364
+ @read_port = nil
365
+ @write_port = nil
366
+
349
367
  # The reader input ports by name.
350
368
  @reader_inputs = {}
351
369
  # The reader output ports by name.
@@ -367,11 +385,6 @@ module HDLRuby::High::Std
367
385
  # The accesser inout ports by name.
368
386
  @accesser_inouts = {}
369
387
 
370
- # # The default reset procedures (reseters), by default do nothing.
371
- # @input_reseter_proc = proc {}
372
- # @output_reseter_proc = proc {}
373
- # @inout_reseter_proc = proc {}
374
-
375
388
  # The branch channels
376
389
  @branches = {}
377
390
 
@@ -427,6 +440,11 @@ module HDLRuby::High::Std
427
440
  HDLRuby::High.space_reg(@name) { obj }
428
441
  end
429
442
 
443
+ # Get the parent system.
444
+ def parent_system
445
+ return self.scope.parent_system
446
+ end
447
+
430
448
  # The methods for defining the channel
431
449
 
432
450
  # For the channel itself
@@ -606,6 +624,12 @@ module HDLRuby::High::Std
606
624
  @writer_inouts.values
607
625
  end
608
626
 
627
+ ## Tells if the channel support inout port.
628
+ def inout?
629
+ return @accesser_inputs.any? || @accesser_outputs.any? ||
630
+ @accesser_inouts.any?
631
+ end
632
+
609
633
  # Defines a branch in the channel named +name+ built executing
610
634
  # +ruby_block+.
611
635
  # Alternatively, a ready channel instance can be passed as argument
@@ -620,8 +644,7 @@ module HDLRuby::High::Std
620
644
  @branches[name] = channelI
621
645
  return self
622
646
  end
623
- # No, create the branch.
624
- # channelI = HDLRuby::High.channel_instance(name, &ruby_block)
647
+ # Now, create the branch.
625
648
  channelI = HDLRuby::High::Std.channel_instance(name, &ruby_block)
626
649
  @branches[name] = channelI
627
650
  return self
@@ -644,54 +667,83 @@ module HDLRuby::High::Std
644
667
 
645
668
  # Reader, writer and accesser side.
646
669
 
647
- ## Declares the ports for the reader and assigned them to +name+.
648
- def input(name)
670
+ ## Declares the reader port as and assigned them to +name+.
671
+ def input(name = nil)
649
672
  # Ensure name is a symbol.
673
+ name = HDLRuby.uniq_name unless name
650
674
  name = name.to_sym
675
+ # Ensure the port is not already existing.
676
+ if @read_port then
677
+ raise "Read port already declared for channel instance: " +
678
+ self.name
679
+ end
680
+
651
681
  # Access the ports
652
- loc_inputs = @reader_inputs
653
- loc_outputs = @reader_outputs
654
- loc_inouts = @reader_inouts
682
+ # loc_inputs = @reader_inputs
683
+ # loc_outputs = @reader_outputs
684
+ # loc_inouts = @reader_inouts
685
+ loc_inputs = @reader_inputs.merge(@accesser_inputs)
686
+ loc_outputs = @reader_outputs.merge(@accesser_outputs)
687
+ loc_inouts = @reader_inouts.merge(@accesser_inouts)
688
+ locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
655
689
  # The generated port with corresponding channel port pairs.
656
690
  port_pairs = []
657
- # Add them to the current system.
658
- HDLRuby::High.cur_system.open do
659
- # The inputs
660
- loc_inputs.each do |name,sig|
661
- # puts "name=#{name} sig.name=#{sig.name}"
662
- port_pairs << [sig, sig.type.input(name)]
691
+ if HDLRuby::High.cur_system == self.parent_system then
692
+ # Port in same system as the channel case.
693
+ # Add them to the current system.
694
+ HDLRuby::High.cur_system.open do
695
+ locs.each do |name,sig|
696
+ port_pairs << [sig, sig.type.inner(name)]
697
+ end
663
698
  end
664
- # The outputs
665
- loc_outputs.each do |name,sig|
666
- port_pairs << [sig, sig.type.output(name)]
699
+ obj = self
700
+ # Make the inner connection
701
+ port_pairs.each do |sig, port|
702
+ sig.parent.open do
703
+ port.to_ref <= sig
704
+ end
667
705
  end
668
- # The inouts
669
- loc_inouts.each do |name,sig|
670
- port_pairs << [sig, sig.type.inout(name)]
706
+ else
707
+ # Port in different system as the channel case.
708
+ # Add them to the current system.
709
+ HDLRuby::High.cur_system.open do
710
+ # The inputs
711
+ loc_inputs.each do |name,sig|
712
+ # puts "name=#{name} sig.name=#{sig.name}"
713
+ port_pairs << [sig, sig.type.input(name)]
714
+ end
715
+ # The outputs
716
+ loc_outputs.each do |name,sig|
717
+ port_pairs << [sig, sig.type.output(name)]
718
+ end
719
+ # The inouts
720
+ loc_inouts.each do |name,sig|
721
+ port_pairs << [sig, sig.type.inout(name)]
722
+ end
671
723
  end
672
- end
673
- obj = self
674
- # Make the connection of the instance.
675
- HDLRuby::High.cur_system.on_instance do |inst|
676
- obj.scope.open do
677
- port_pairs.each do |sig, port|
678
- RefObject.new(inst,port.to_ref) <= sig
724
+ obj = self
725
+ # Make the connection of the instance.
726
+ HDLRuby::High.cur_system.on_instance do |inst|
727
+ obj.scope.open do
728
+ port_pairs.each do |sig, port|
729
+ RefObject.new(inst,port.to_ref) <= sig
730
+ end
679
731
  end
680
732
  end
681
733
  end
682
734
 
683
735
  # Fill the reader namespace with the access to the reader signals.
684
- @reader_inputs.each do |name,sig|
736
+ loc_inputs.each do |name,sig|
685
737
  @reader_namespace.add_method(sig.name) do
686
738
  HDLRuby::High.top_user.send(name)
687
739
  end
688
740
  end
689
- @reader_outputs.each do |name,sig|
741
+ loc_outputs.each do |name,sig|
690
742
  @reader_namespace.add_method(sig.name) do
691
743
  HDLRuby::High.top_user.send(name)
692
744
  end
693
745
  end
694
- @reader_inouts.each do |name,sig|
746
+ loc_inouts.each do |name,sig|
695
747
  @reader_namespace.add_method(sig.name) do
696
748
  HDLRuby::High.top_user.send(name)
697
749
  end
@@ -701,56 +753,88 @@ module HDLRuby::High::Std
701
753
  # NOTE: for now, simply associate the channel to name.
702
754
  chp = ChannelPortR.new(@reader_namespace,@reader_proc,@input_reseter_proc)
703
755
  HDLRuby::High.space_reg(name) { chp }
756
+ # Save the port in the channe to avoid conflicting declaration.
757
+ @read_port = chp
704
758
  return chp
705
759
  end
706
760
 
707
761
  ## Declares the ports for the writer and assigned them to +name+.
708
- def output(name)
762
+ def output(name = nil)
709
763
  # Ensure name is a symbol.
764
+ name = HDLRuby.uniq_name unless name
710
765
  name = name.to_sym
766
+ # Ensure the port is not already existing.
767
+ if @write_port then
768
+ raise "Write port already declared for channel instance: " +
769
+ self.name
770
+ end
711
771
  # Access the ports
712
- loc_inputs = @writer_inputs
713
- loc_outputs = @writer_outputs
714
- loc_inouts = @writer_inouts
772
+ # loc_inputs = @writer_inputs
773
+ # loc_outputs = @writer_outputs
774
+ # loc_inouts = @writer_inouts
775
+ loc_inputs = @writer_inputs.merge(@accesser_inputs)
776
+ loc_outputs = @writer_outputs.merge(@accesser_outputs)
777
+ loc_inouts = @writer_inouts.merge(@accesser_inouts)
778
+ locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
715
779
  # The generated port with corresponding channel port pairs.
716
780
  port_pairs = []
717
- # Add them to the current system.
718
- HDLRuby::High.cur_system.open do
719
- # The inputs
720
- loc_inputs.each do |name,sig|
721
- port_pairs << [sig, sig.type.input(name)]
781
+ # puts "cur_system=#{HDLRuby::High.cur_system} self.parent_system=#{self.parent_system}"
782
+ if HDLRuby::High.cur_system == self.parent_system then
783
+ # puts "Inner found!"
784
+ # Port in same system as the channel case.
785
+ # Add them to the current system.
786
+ HDLRuby::High.cur_system.open do
787
+ locs.each do |name,sig|
788
+ port_pairs << [sig, sig.type.inner(name)]
789
+ end
722
790
  end
723
- # The outputs
724
- loc_outputs.each do |name,sig|
725
- port_pairs << [sig, sig.type.output(name)]
791
+ obj = self
792
+ # Make the inner connection
793
+ port_pairs.each do |sig, port|
794
+ sig.parent.open do
795
+ port.to_ref <= sig
796
+ end
726
797
  end
727
- # The inouts
728
- loc_inouts.each do |name,sig|
729
- port_pairs << [sig, sig.type.inout(name)]
798
+ else
799
+ # Portds in different system as the channel's case.
800
+ # Add them to the current system.
801
+ HDLRuby::High.cur_system.open do
802
+ # The inputs
803
+ loc_inputs.each do |name,sig|
804
+ port_pairs << [sig, sig.type.input(name)]
805
+ end
806
+ # The outputs
807
+ loc_outputs.each do |name,sig|
808
+ port_pairs << [sig, sig.type.output(name)]
809
+ end
810
+ # The inouts
811
+ loc_inouts.each do |name,sig|
812
+ port_pairs << [sig, sig.type.inout(name)]
813
+ end
730
814
  end
731
- end
732
- obj = self
733
- # Make the connection of the instance.
734
- HDLRuby::High.cur_system.on_instance do |inst|
735
- obj.scope.open do
736
- port_pairs.each do |sig, port|
737
- RefObject.new(inst,port.to_ref) <= sig
815
+ obj = self
816
+ # Make the connection of the instance.
817
+ HDLRuby::High.cur_system.on_instance do |inst|
818
+ obj.scope.open do
819
+ port_pairs.each do |sig, port|
820
+ RefObject.new(inst,port.to_ref) <= sig
821
+ end
738
822
  end
739
823
  end
740
824
  end
741
825
 
742
826
  # Fill the writer namespace with the access to the writer signals.
743
- @writer_inputs.each do |name,sig|
827
+ loc_inputs.each do |name,sig|
744
828
  @writer_namespace.add_method(sig.name) do
745
829
  HDLRuby::High.top_user.send(name)
746
830
  end
747
831
  end
748
- @writer_outputs.each do |name,sig|
832
+ loc_outputs.each do |name,sig|
749
833
  @writer_namespace.add_method(sig.name) do
750
834
  HDLRuby::High.top_user.send(name)
751
835
  end
752
836
  end
753
- @writer_inouts.each do |name,sig|
837
+ loc_inouts.each do |name,sig|
754
838
  @writer_namespace.add_method(sig.name) do
755
839
  HDLRuby::High.top_user.send(name)
756
840
  end
@@ -760,73 +844,28 @@ module HDLRuby::High::Std
760
844
  # NOTE: for now, simply associate the channel to name.
761
845
  chp = ChannelPortW.new(@writer_namespace,@writer_proc,@output_reseter_proc)
762
846
  HDLRuby::High.space_reg(name) { chp }
847
+ # Save the port in the channe to avoid conflicting declaration.
848
+ @write_port = chp
763
849
  return chp
764
850
  end
765
851
 
766
- ## Declares the ports for the accesser and assigned them to +name+.
767
- def inout(name)
852
+
853
+ ## Declares the accesser port and assigned them to +name+.
854
+ def inout(name = nil)
768
855
  # Ensure name is a symbol.
856
+ name = HDLRuby.uniq_name unless name
769
857
  name = name.to_sym
770
- # Access the ports
771
- loc_inputs = @accesser_inputs
772
- loc_outputs = @accesser_outputs
773
- loc_inouts = @accesser_inouts
774
- # The generated port with corresponding channel port pairs.
775
- port_pairs = []
776
- # Add them to the current system.
777
- HDLRuby::High.cur_system.open do
778
- # The inputs
779
- loc_inputs.each do |name,sig|
780
- port_pairs << [sig, sig.type.input(name)]
781
- end
782
- # The outputs
783
- loc_outputs.each do |name,sig|
784
- port_pairs << [sig, sig.type.output(name)]
785
- end
786
- # The inouts
787
- loc_inouts.each do |name,sig|
788
- port_pairs << [sig, sig.type.inout(name)]
789
- end
790
- end
791
- obj = self
792
- # Make the connection of the instance.
793
- HDLRuby::High.cur_system.on_instance do |inst|
794
- obj.scope.open do
795
- port_pairs.each do |sig, port|
796
- RefObject.new(inst,port.to_ref) <= sig
797
- end
798
- end
858
+ # Ensure the port is not already existing.
859
+ if @read_port then
860
+ raise "Read port already declared for channel instance: " +
861
+ self.name
799
862
  end
800
863
 
801
- # Set ups the accesser's namespace
802
- @accesser_inputs.each do |name,sig|
803
- @accesser_namespace.add_method(sig.name) do
804
- HDLRuby::High.top_user.send(name)
805
- end
864
+ if @write_port then
865
+ raise "Write port already declared for channel instance: " +
866
+ self.name
806
867
  end
807
- @accesser_outputs.each do |name,sig|
808
- @accesser_namespace.add_method(sig.name) do
809
- HDLRuby::High.top_user.send(name)
810
- end
811
- end
812
- @accesser_inouts.each do |name,sig|
813
- @accesser_namespace.add_method(sig.name) do
814
- HDLRuby::High.top_user.send(name)
815
- end
816
- end
817
-
818
- # Give access to the ports through name.
819
- # NOTE: for now, simply associate the channel to name.
820
- chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
821
- HDLRuby::High.space_reg(name) { chp }
822
- return chp
823
- end
824
868
 
825
- ## Declares the ports for accessing the channel as an inner component
826
- # and assigned them to +name+.
827
- def inner(name)
828
- # Ensure name is a symbol.
829
- name = name.to_sym
830
869
  # Access the ports
831
870
  loc_inputs = @accesser_inputs.merge(@reader_inputs).
832
871
  merge(@writer_inputs)
@@ -837,21 +876,51 @@ module HDLRuby::High::Std
837
876
  locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
838
877
  # The generated port with corresponding channel port pairs.
839
878
  port_pairs = []
840
- # Add them to the current system.
841
- HDLRuby::High.cur_system.open do
842
- locs.each do |name,sig|
843
- port_pairs << [sig, sig.type.inner(name)]
879
+ if HDLRuby::High.cur_system == self.parent_system then
880
+ # Port in same system as the channel case.
881
+ # Add them to the current system.
882
+ HDLRuby::High.cur_system.open do
883
+ locs.each do |name,sig|
884
+ port_pairs << [sig, sig.type.inner(name)]
885
+ end
844
886
  end
845
- end
846
- obj = self
847
- # Make the inner connection
848
- port_pairs.each do |sig, port|
849
- sig.parent.open do
850
- port.to_ref <= sig
887
+ obj = self
888
+ # Make the inner connection
889
+ port_pairs.each do |sig, port|
890
+ sig.parent.open do
891
+ port.to_ref <= sig
892
+ end
893
+ end
894
+ else
895
+ # Port in different system as the channel case.
896
+ # Add them to the current system.
897
+ HDLRuby::High.cur_system.open do
898
+ # The inputs
899
+ loc_inputs.each do |name,sig|
900
+ # puts "name=#{name} sig.name=#{sig.name}"
901
+ port_pairs << [sig, sig.type.input(name)]
902
+ end
903
+ # The outputs
904
+ loc_outputs.each do |name,sig|
905
+ port_pairs << [sig, sig.type.output(name)]
906
+ end
907
+ # The inouts
908
+ loc_inouts.each do |name,sig|
909
+ port_pairs << [sig, sig.type.inout(name)]
910
+ end
911
+ end
912
+ obj = self
913
+ # Make the connection of the instance.
914
+ HDLRuby::High.cur_system.on_instance do |inst|
915
+ obj.scope.open do
916
+ port_pairs.each do |sig, port|
917
+ RefObject.new(inst,port.to_ref) <= sig
918
+ end
919
+ end
851
920
  end
852
921
  end
853
922
 
854
- # Set ups the accesser's namespace
923
+ # Fill the reader namespace with the access to the reader signals.
855
924
  loc_inputs.each do |name,sig|
856
925
  @accesser_namespace.add_method(sig.name) do
857
926
  HDLRuby::High.top_user.send(name)
@@ -872,37 +941,121 @@ module HDLRuby::High::Std
872
941
  # NOTE: for now, simply associate the channel to name.
873
942
  chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
874
943
  HDLRuby::High.space_reg(name) { chp }
944
+ # Save the port in the channe to avoid conflicting declaration.
945
+ @read_port = chp
946
+ @write_port = chp
875
947
  return chp
876
948
  end
877
949
 
950
+ # ## Declares the ports for accessing the channel as an inner component
951
+ # # and assigned them to +name+.
952
+ # def inner(name)
953
+ # # Ensure name is a symbol.
954
+ # name = name.to_sym
955
+ # # Access the ports
956
+ # loc_inputs = @accesser_inputs.merge(@reader_inputs).
957
+ # merge(@writer_inputs)
958
+ # loc_outputs = @accesser_outputs.merge(@reader_outputs).
959
+ # merge(@writer_outputs)
960
+ # loc_inouts = @accesser_inouts.merge(@reader_inouts).
961
+ # merge(@writer_inouts)
962
+ # locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
963
+ # # The generated port with corresponding channel port pairs.
964
+ # port_pairs = []
965
+ # # Add them to the current system.
966
+ # HDLRuby::High.cur_system.open do
967
+ # locs.each do |name,sig|
968
+ # port_pairs << [sig, sig.type.inner(name)]
969
+ # end
970
+ # end
971
+ # obj = self
972
+ # # Make the inner connection
973
+ # port_pairs.each do |sig, port|
974
+ # sig.parent.open do
975
+ # port.to_ref <= sig
976
+ # end
977
+ # end
978
+
979
+ # # Set ups the accesser's namespace
980
+ # loc_inputs.each do |name,sig|
981
+ # @accesser_namespace.add_method(sig.name) do
982
+ # HDLRuby::High.top_user.send(name)
983
+ # end
984
+ # end
985
+ # loc_outputs.each do |name,sig|
986
+ # @accesser_namespace.add_method(sig.name) do
987
+ # HDLRuby::High.top_user.send(name)
988
+ # end
989
+ # end
990
+ # loc_inouts.each do |name,sig|
991
+ # @accesser_namespace.add_method(sig.name) do
992
+ # HDLRuby::High.top_user.send(name)
993
+ # end
994
+ # end
995
+
996
+ # # Give access to the ports through name.
997
+ # # NOTE: for now, simply associate the channel to name.
998
+ # chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
999
+ # HDLRuby::High.space_reg(name) { chp }
1000
+ # return chp
1001
+ # end
1002
+
1003
+
878
1004
 
879
1005
  ## Performs a read on the channel using +args+ and +ruby_block+
880
1006
  # as arguments.
1007
+ # NOTE:
1008
+ # * Will generate a port if not present.
1009
+ # * Will generate an error if a read is tempted while the read
1010
+ # port has been declared within another system.
881
1011
  def read(*args,&ruby_block)
882
- # Gain access to the reader as local variable.
883
- reader_proc = @reader_proc
884
- # # The context is the one of the reader.
885
- # Execute the code generating the reader in context.
886
- HDLRuby::High.space_push(@namespace)
887
- HDLRuby::High.cur_block.open do
888
- instance_exec(ruby_block,*args,&reader_proc)
1012
+ # Is there a port to read?
1013
+ unless self.read_port then
1014
+ # No, generate a new one.
1015
+ # Is it possible to be inout?
1016
+ if self.inout? then
1017
+ # Yes, create an inout port.
1018
+ self.inout(HDLRuby.uniq_name)
1019
+ else
1020
+ # No, create an input port.
1021
+ self.input(HDLRuby.uniq_name)
1022
+ end
889
1023
  end
890
- HDLRuby::High.space_pop
1024
+ # Ensure the read port is within current system.
1025
+ unless self.read_port.scope.system != HDLRuby::High.cur_system then
1026
+ raise "Cannot read from a port external of current system for channel " + self.name
1027
+ end
1028
+ # Performs the read.
1029
+ self.read_port.read(*args,&ruby_block)
891
1030
  end
892
1031
 
893
1032
  ## Performs a write on the channel using +args+ and +ruby_block+
894
1033
  # as arguments.
1034
+ # NOTE:
1035
+ # * Will generate a port if not present.
1036
+ # * Will generate an error if a read is tempted while the read
1037
+ # port has been declared within another system.
895
1038
  def write(*args,&ruby_block)
896
- # Gain access to the writer as local variable.
897
- writer_proc = @writer_proc
898
- # # The context is the one of the writer.
899
- # Execute the code generating the writer in context.
900
- HDLRuby::High.space_push(@namespace)
901
- HDLRuby::High.cur_block.open do
902
- instance_exec(ruby_block,*args,&writer_proc)
1039
+ # Is there a port to write?
1040
+ unless self.write_port then
1041
+ # No, generate a new one.
1042
+ # Is it possible to be inout?
1043
+ if self.inout? then
1044
+ # Yes, create an inout port.
1045
+ self.inout(HDLRuby.uniq_name)
1046
+ else
1047
+ # No, create an output port.
1048
+ self.output(HDLRuby.uniq_name)
1049
+ end
903
1050
  end
904
- HDLRuby::High.space_pop
1051
+ # Ensure the write port is within current system.
1052
+ unless self.write_port.scope.system != HDLRuby::High.cur_system then
1053
+ raise "Cannot write from a port external of current system for channel " + self.name
1054
+ end
1055
+ # Performs the write.
1056
+ self.write_port.write(*args,&ruby_block)
905
1057
  end
1058
+
906
1059
 
907
1060
  ## Performs a reset on the channel using +args+ and +ruby_block+
908
1061
  # as arguments.
@@ -925,6 +1078,8 @@ module HDLRuby::High::Std
925
1078
  # Create a new object wrapper for +obj+.
926
1079
  def initialize(obj)
927
1080
  @obj = obj
1081
+
1082
+ @scope = HDLRuby::High.cur_scope
928
1083
  end
929
1084
 
930
1085
  # Port read with arguments +args+ executing +ruby_block+ in
@@ -889,11 +889,11 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
889
889
  rst_name = br_rsts[:winc].to_sym
890
890
  else
891
891
  rst_name = rst.name
892
- reader_input rst_name
892
+ writer_input rst_name
893
893
  end
894
894
  # Declares the address counter.
895
895
  [size.width-1].inner :abus_w
896
- reader_inout :abus_w
896
+ writer_inout :abus_w
897
897
 
898
898
  # Defines the write procedure at address +addr+
899
899
  # using +target+ as target of access result.
@@ -1,3 +1,3 @@
1
1
  module HDLRuby
2
- VERSION = "2.3.2"
2
+ VERSION = "2.3.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: HDLRuby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 2.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lovic Gauthier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-30 00:00:00.000000000 Z
11
+ date: 2020-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler