katcp 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b2ff660c3d5dc7a953d33929f927b4db105090e1
4
+ data.tar.gz: 260e11b31ab6bdffa5be4e1a0ce0038027a793da
5
+ SHA512:
6
+ metadata.gz: ced30aa287a9971789e7c387a2b5f8f294891c318fe9d3a28e806a12450a44adc3baf20e91a7d589611d3a136260bd46dae20a99390f55611bdba2fc4a8b218d
7
+ data.tar.gz: 618cba5da5aa45443a093ff558f03f14ae3bf936815c69985c4d326007fb45db068a65fa84d72903a94ee4c2a1f83fb6996f8d1f418253b3c9784944e869ac27
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ require 'katcp'
6
+
7
+ OPTS = {
8
+ :verbose => false
9
+ }
10
+
11
+ ARGV.options do |op|
12
+ op.program_name = File.basename($0)
13
+
14
+ op.banner = "Usage: #{op.program_name} [OPTIONS] HOST[:PORT] [CMD [ARGS]]"
15
+ op.separator('')
16
+ op.separator('Runs KATCP command CMD with (optional) arguments ARGS on HOST.')
17
+ op.separator('If CMD is not given, just connect and print inform messages.')
18
+ op.separator('Non-standard port can be given as HOST:PORT.')
19
+ op.separator('')
20
+ op.separator("Example: #{op.program_name} roach2 progdev my_design.bof")
21
+ op.separator('')
22
+ op.separator 'Options:'
23
+ op.on_tail("-v", "--[no-]verbose", "Prints inform messages") do |o|
24
+ OPTS[:verbose] = o
25
+ end
26
+ op.on_tail("-h", "--help", "Show this message") do
27
+ puts op
28
+ exit 1
29
+ end
30
+ op.parse!
31
+ end
32
+
33
+ if ARGV.empty?
34
+ puts ARGV.options
35
+ exit 1
36
+ end
37
+
38
+ host, port = ARGV.shift.split(':')
39
+ port ||= ENV['KATCP_PORT'] || '7147'
40
+ port = Integer(port) rescue 7147
41
+
42
+ cmd = ARGV.shift
43
+
44
+ exit_status = 0
45
+
46
+ r = KATCP::RoachClient.new(host, port)
47
+
48
+ if cmd
49
+ informs = r.informs(true)
50
+ puts informs if OPTS[:verbose]
51
+
52
+ resp = r.respond_to?(cmd) ? r.send(cmd, *ARGV) : r.request(cmd, *ARGV)
53
+
54
+ case resp
55
+ when KATCP::Response
56
+ puts resp
57
+ exit_status = resp.ok? ? 0 : 1
58
+ when KATCP::Client
59
+ # Print log informs
60
+ puts resp.informs(true).grep(/^#log/)
61
+ # Handle programmed? and other true/false operations
62
+ when true
63
+ puts resp if OPTS[:verbose]
64
+ exit_status = 0
65
+ when false
66
+ puts resp if OPTS[:verbose]
67
+ exit_status = 1
68
+ else
69
+ puts "got a #{resp.class}: #{resp.inspect}"
70
+ end
71
+
72
+ puts r.informs(true) if OPTS[:verbose]
73
+ else
74
+ puts r.informs(true)
75
+ end
76
+
77
+ r.close
78
+
79
+ exit exit_status
@@ -383,7 +383,7 @@ module KATCP
383
383
  # call-seq:
384
384
  # sensor_dump(*args) -> KATCP::Response
385
385
  #
386
- # Dumps the sensor tree.
386
+ # Dumps the sensor tree. [obsolete?]
387
387
  def sensor_dump(*args)
388
388
  request(:sensor_dump, *args)
389
389
  end
@@ -68,6 +68,8 @@ module KATCP
68
68
  # Returns xaui status word. Bits 2 through 5 are lane sync, bit 6 is
69
69
  # channel bonding status.
70
70
  def xaui_status; get(9); end
71
+ # Returns true if all four lanes are sync'd and bonded.
72
+ def xaui_status_ok?; (get(9) & 0b01111100) == 0b01111100; end
71
73
  # Four least significant bits represent sync status for each lane.
72
74
  # 1 bit = lane sync OK
73
75
  # 0 bit = lane sync BAD
@@ -77,7 +79,7 @@ module KATCP
77
79
  # Returns true if #xaui_sync returns 15
78
80
  def xaui_sync_ok?; xaui_sync == 0b1111; end
79
81
  # Returns true if all four XAUI lanes are bonded
80
- def xaui_bonded?; (get(9) >> 6) & 1; end
82
+ def xaui_bonded?; ((get(9) >> 6) & 1) == 1; end
81
83
 
82
84
  # Get current value of rx_eq_mix parameter.
83
85
  def rx_eq_mix ; (get(10) >> 24) & 0xff; end
@@ -97,6 +99,69 @@ module KATCP
97
99
  def []=(idx, mac)
98
100
  write64(0xc00+2*idx, mac)
99
101
  end
102
+ end # class TenGE
103
+
104
+ # Class used to access CASPER Snapshot blocks. +device_name+ must be used
105
+ # with the bram or dram device in the snapshot block. Other devices in the
106
+ # snapshot block may be hidden/ignored with :skip in the device_typemap or
107
+ # may be exposed/used if desired. Currently this class only uses the memory
108
+ # element and the "trig" register; it does not directly use the "status"
109
+ # register or the optional "trig_offset" or "tr_en_cnt" registers.
110
+ class Snapshot < Bram
111
+ def initialize(katcp_client, device_name)
112
+ super
113
+ @ctrl_name = device_name.sub(/_[bd]ram$/, '_ctrl')
114
+ end
115
+
116
+ # Validate and massage method name
117
+ def self.method_name(name)
118
+ if name !~ /_[bd]ram$/
119
+ raise "invalid name '#{name}' for #{self.name}"
120
+ end
121
+ name.sub!(/_[bd]ram$/, '')
122
+ end
123
+
124
+ # Trigger a new snapshot. +opts+ can be used to control the trigger type
125
+ # using the :trigger key and the write enable using the :wren key:
126
+ #
127
+ # :trigger => :internal means trigger right away
128
+ # :trigger => :external means trigger on the block's trigger input
129
+ # :wren => :internal means to capture every FPGA clock cycle
130
+ # :wren => :external means to capture when the block's we input is high
131
+ #
132
+ # The default behavior is :internal for both.
133
+ def trigger(opts={})
134
+ # Assume internal for both
135
+ trigval = 6
136
+ # Turn off bits if external
137
+ trigval ^= 2 if /^ext/ =~ (opts[:trigger]||opts[:trig])
138
+ trigval ^= 4 if /^ext/ =~ opts[:wren]
139
+ @katcp_client.write(@ctrl_name, trigval)
140
+ @katcp_client.write(@ctrl_name, trigval|1)
141
+ @katcp_client.write(@ctrl_name, trigval)
142
+ end
143
+ end # class Snapshot
144
+
145
+ # Class used to access QDR controller cores
146
+ class QdrCtrl < Bram
147
+ # Resets the QDR controller (re-calibrates)
148
+ def reset
149
+ self[0] = 0
150
+ self[1] = 0xffff_ffff
151
+ self[0] = 0
152
+ end
153
+
154
+ # Returns state of cal_fail bit
155
+ def cal_fail?
156
+ # Bit 8
157
+ (self[1] & (1<<8)) != 0
158
+ end
159
+
160
+ # Returns state of phy_rdy bit (
161
+ def phy_rdy?
162
+ # Bit 0
163
+ (self[1] & (1<<0)) != 0
164
+ end
100
165
  end
101
166
 
102
167
  # Facilitates talking to <tt>tcpborphserver2</tt>, a KATCP server
@@ -146,9 +211,12 @@ module KATCP
146
211
  # :local_port Specifies local port to bind to (default nil)
147
212
  # :socket_timeout Specifies timeout for socket operations
148
213
  # (default DEFAULT_SOCKET_TIMEOUT)
149
- # :typemap Provides a default device typemap (default {}).
150
- # See #device_typemap for details.
214
+ # :typemap Provides a way to override the default device typemap
215
+ # (default {}). See #device_typemap for details.
151
216
  def initialize(*args)
217
+ # If final arg is a Hash, pop it off
218
+ @opts = (Hash === args[-1]) ? args.pop : {}
219
+
152
220
  # List of all devices
153
221
  @devices = [];
154
222
  # List of dynamically defined device attrs (readers only, writers implied)
@@ -156,7 +224,11 @@ module KATCP
156
224
  # @device objects is a Hash of created device objects: key is Class,
157
225
  # value is a Hash mapping device name to instance of Class.
158
226
  @device_objects = {}
159
- # Call super *after* initializing subclass instance variables
227
+ # Merge @opts[:typemap] (if given) into device_typemap.
228
+ # This must be done *before* calling super.
229
+ device_typemap.merge!(@opts[:typemap]) if @opts[:typemap]
230
+ # Call super *after* initializing instance variables and possibly
231
+ # updating typemap.
160
232
  super(*args)
161
233
  end
162
234
 
@@ -206,14 +278,20 @@ module KATCP
206
278
  type, *aliases = typemap[dev] || typemap[dev.to_sym]
207
279
  next if type == :skip
208
280
  # Dynamically define methods and aliases
209
- case type
210
- when Class; device_object(type, dev, *aliases)
211
- when :bram; device_object(Bram, dev, *aliases)
212
- when :tenge; device_object(TenGE, dev, *aliases)
213
- when :roreg; roreg(dev, *aliases)
214
- # else :rwreg or nil (or anything else for that matter) so treat it
215
- # as R/W register.
216
- else rwreg(dev, *aliases)
281
+ begin
282
+ case type
283
+ when Class; device_object(type, dev, *aliases)
284
+ when :bram; device_object(Bram, dev, *aliases)
285
+ when :tenge; device_object(TenGE, dev, *aliases)
286
+ when :snap; device_object(Snapshot, dev, *aliases)
287
+ when :qdrctrl; device_object(QdrCtrl, dev, *aliases)
288
+ when :roreg; roreg(dev, *aliases)
289
+ # else :rwreg or nil (or anything else for that matter) so treat it
290
+ # as R/W register.
291
+ else rwreg(dev, *aliases)
292
+ end
293
+ rescue => e
294
+ STDERR.puts e
217
295
  end
218
296
  end
219
297
  end
@@ -237,6 +315,45 @@ module KATCP
237
315
 
238
316
  protected :undefine_device_attrs
239
317
 
318
+ # This is the default (empty) typemap. It exists here so that subclasses
319
+ # (and their subclasses) have the option of using the following idiom to
320
+ # create their own custom typemap that includes their superclass's typemap:
321
+ #
322
+ # class SomeClass < KATCP::RoachClient
323
+ # DEVICE_TYPEMAP = superclass::DEVICE_TYPEMAP.merge({
324
+ # :some_device => :rwreg
325
+ # })
326
+ # ...
327
+ # end
328
+ #
329
+ # class MyClass < SomeClass
330
+ # DEVICE_TYPEMAP = superclass::DEVICE_TYPEMAP.merge({
331
+ # :switch_gbe_status => :roreg,
332
+ # :switch_gbe => :tenge,
333
+ # :adc_rms_levels => :bram
334
+ # })
335
+ # ...
336
+ # end
337
+ #
338
+ # As defined above, MyClass::DEVICE_TYPEMAP will be:
339
+ #
340
+ # {
341
+ # :some_device => :rwreg,
342
+ # :switch_gbe_status => :roreg,
343
+ # :switch_gbe => :tenge,
344
+ # :adc_rms_levels => :bram
345
+ # }
346
+ #
347
+ # Because the superclass of SomeClass is KATCP::RoachClient, the
348
+ # "superclass::DEVICE_TYPEMAP.merge" part is optional in SomeClass, but it
349
+ # is still recommended since future versions of KATCP::RoachClient may have
350
+ # a non-empty typemap.
351
+ DEVICE_TYPEMAP = {}
352
+
353
+ # Returns the default device typemap Hash (either the one passed to the
354
+ # constructor or an empty Hash). Design specific subclasses can override
355
+ # this method to return a design specific device typemap.
356
+ #
240
357
  # This method's return value controls how methods and aliases are
241
358
  # dynamically generated for devices within the ROACH gateware. If
242
359
  # #device_typemap returns +nil+ or an empty Hash, all devices will be
@@ -259,7 +376,36 @@ module KATCP
259
376
  # will be created. The returned TenGE object
260
377
  # provides convenient ways to read and write
261
378
  # to the TenGE device.
379
+ # :snap (Snapshot) A reader method returning a Snapshot object
380
+ # will be created. The returned Snapshot
381
+ # object provides a trigger method and acts
382
+ # like a Bram object for the Snapshot's
383
+ # memory element. Must be used with the
384
+ # snapshot block's BRAM (or DRAM) device.
385
+ # :qdrctrl (QDR controller) A reader method returning a QdrCtrl object
386
+ # will be created. The returned QdrCtrl
387
+ # object provides methods to reset the QDR
388
+ # controller and check its cal_fail and
389
+ # phy_rdy status bits.
262
390
  # :skip (unwanted device) No method will be created.
391
+ # A class name (custom) A user-supplied class can be given to
392
+ # allow for customized device access.
393
+ #
394
+ # If a class name is specified, the method defined for the corresponding
395
+ # device will return an instance of the given class. The constructor will
396
+ # be passed the KATCP::Client instance and a String specifying the device
397
+ # name. Here is an example of a suitable class definition:
398
+ #
399
+ # class MyDevice
400
+ # def initialize(katcp_client, device_name)
401
+ # # Save client and device name for future use
402
+ # @katcp_client = katcp_client
403
+ # @device_name = device_name
404
+ # end
405
+ #
406
+ # # Other functionality defined here
407
+ #
408
+ # end # class MyDevice
263
409
  #
264
410
  # Methods are only created for devices that actually exist on the device.
265
411
  # If no device exists for a given key, no methods will be created for that
@@ -267,9 +413,9 @@ module KATCP
267
413
  # created unless they are backed by an actual device. Both reader and
268
414
  # writer methods are created for devices for which no key is present.
269
415
  #
270
- # The value can also be an Array whose first element is a Symbol from the
271
- # list above. The remaining elements specify aliases to be created for the
272
- # given attribute methods.
416
+ # The value can also be an Array whose first element is a Symbol (or class
417
+ # name) from the list above. The remaining elements specify aliases to be
418
+ # created for the given attribute methods.
273
419
  #
274
420
  # RoachClient#device_typemap returns on empty Hash so all devices are
275
421
  # treated as read/write registers by default. Gateware specific subclasses
@@ -278,29 +424,33 @@ module KATCP
278
424
  #
279
425
  # Example: The following would lead to the creation of the following
280
426
  # methods and aliases: "input_selector", "input_selector=", "insel",
281
- # "insel=", "switch_gbe_status", "switch_gbe", "adc_rms_levels" (assuming
282
- # the named devices all exist!). No methods would be created for the
283
- # device named "unwanted_reg" even if it exists.
427
+ # "insel=", "switch_gbe_status", "switch_gbe", "adc_rms_levels", and
428
+ # "my_device" (assuming the named devices all exist!). No methods would be
429
+ # created for the device named "unwanted_reg" even if it exists.
284
430
  #
285
431
  # class MyRoachDesign < RoachClient
286
- # DEVICE_TYPEMAP = {
432
+ # DEVICE_TYPEMAP = superclass::DEVICE_TYPEMAP.merge({
287
433
  # :input_selector => [:rwreg, :insel],
288
434
  # :switch_gbe_status => :roreg,
289
435
  # :switch_gbe => :tenge,
290
436
  # :adc_rms_levels => :bram,
437
+ # :my_device => MyDevice,
291
438
  # :unwanted_reg => :skip
292
- # }
439
+ # })
293
440
  #
294
441
  # def device_typemap
295
- # DEVICE_TYPEMAP
442
+ # @device_typemap ||= DEVICE_TYPEMAP.dup
296
443
  # end
297
444
  # end
298
445
  #
299
- # Returns the default device typemap Hash (either the one passed to the
300
- # constructor or an empty Hash). Design specific subclasses can override
301
- # this method to return a design specific device typemap.
446
+ # If the user passes a typemap Hash to the constructor, that Hash is merged
447
+ # into the Hash returned by device_typemap. This can have side effects
448
+ # that might be unwanted if device_typemap returns a Hash that is
449
+ # referenced by a class constant. To avoid that, it is recommended that
450
+ # device_typemap return the instance variable @device_typemap that is
451
+ # lazily initialized with a copy of the class constant as shown above.
302
452
  def device_typemap
303
- (@opts && @opts[:typemap]) || {}
453
+ @device_typemap ||= DEVICE_TYPEMAP.dup
304
454
  end
305
455
 
306
456
  # Allow subclasses to create read accessor method (with optional aliases)
@@ -355,6 +505,9 @@ module KATCP
355
505
  def device_object(clazz, name, *aliases) # :nodoc:
356
506
  name = name.to_s
357
507
  method_name = name.gsub('/', '_')
508
+ if clazz.respond_to?(:method_name)
509
+ method_name = clazz.method_name(method_name)
510
+ end
358
511
  instance_eval <<-"_end"
359
512
  class << self
360
513
  def #{method_name}()
@@ -463,15 +616,21 @@ module KATCP
463
616
  # attributes that were dynamically defined for the previous design are
464
617
  # removed.
465
618
  def progdev(*args)
619
+ # Clear args (i.e. remove all elements) if first element is nil.
620
+ # This also clears args if it is empty, but that is OK since it is
621
+ # essentially a no-op. Any time saved by not clearing an empty args
622
+ # would be lost by checking whether args is already empty! :-)
623
+ args.clear if args[0].nil?
466
624
  prev_socket_timeout = @socket_timeout
467
625
  begin
468
626
  # Adjust @socket_timeout if programming a bitstream
469
627
  @socket_timeout = PROGDEV_SOCKET_TIMEOUT if args[0]
470
- request(:progdev, *args)
628
+ resp = request(:progdev, *args)
471
629
  ensure
472
630
  @socket_timeout = prev_socket_timeout
473
631
  end
474
632
  define_device_attrs
633
+ resp
475
634
  end
476
635
 
477
636
  # Returns true if currently programmed (specifically, it is equivalent to
@@ -3,5 +3,5 @@
3
3
  #++
4
4
 
5
5
  module KATCP
6
- VERSION = "0.1.8"
6
+ VERSION = "0.1.10"
7
7
  end
metadata CHANGED
@@ -1,48 +1,41 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: katcp
3
- version: !ruby/object:Gem::Version
4
- hash: 11
5
- prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 8
10
- version: 0.1.8
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.10
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - David MacMahon
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2013-04-29 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2013-08-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: narray
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 25
29
- segments:
30
- - 0
31
- - 5
32
- - 9
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
33
19
  version: 0.5.9
34
20
  type: :runtime
35
- version_requirements: *id001
36
- description: " Provides KATCP client library for Ruby. KATCP is the Karoo Array Telescope\n Control Protocol.\n"
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.9
27
+ description: |2
28
+ Provides KATCP client library for Ruby. KATCP is the Karoo Array Telescope
29
+ Control Protocol.
37
30
  email: davidm@astro.berkeley.edu
38
- executables: []
39
-
31
+ executables:
32
+ - katcpcmd.rb
40
33
  extensions: []
41
-
42
- extra_rdoc_files:
34
+ extra_rdoc_files:
43
35
  - README
44
- files:
36
+ files:
45
37
  - README
38
+ - bin/katcpcmd.rb
46
39
  - lib/katcp.rb
47
40
  - lib/katcp/client.rb
48
41
  - lib/katcp/client/roach.rb
@@ -53,41 +46,29 @@ files:
53
46
  - examples/listdev.rb
54
47
  homepage: http://rb-katcp.rubyforge.org/
55
48
  licenses: []
56
-
49
+ metadata: {}
57
50
  post_install_message:
58
- rdoc_options:
51
+ rdoc_options:
59
52
  - -m
60
53
  - README
61
54
  - --title
62
- - Ruby/KATCP 0.1.8 Documentation
63
- require_paths:
55
+ - Ruby/KATCP 0.1.10 Documentation
56
+ require_paths:
64
57
  - lib
65
- required_ruby_version: !ruby/object:Gem::Requirement
66
- none: false
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 53
71
- segments:
72
- - 1
73
- - 8
74
- - 1
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
75
62
  version: 1.8.1
76
- required_rubygems_version: !ruby/object:Gem::Requirement
77
- none: false
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- hash: 3
82
- segments:
83
- - 0
84
- version: "0"
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
85
68
  requirements: []
86
-
87
69
  rubyforge_project: rb-katcp
88
- rubygems_version: 1.8.24
70
+ rubygems_version: 2.0.2
89
71
  signing_key:
90
- specification_version: 3
72
+ specification_version: 4
91
73
  summary: KATCP library for Ruby
92
74
  test_files: []
93
-