origen_link 0.2.0.pre0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/bin/start_link_server +66 -66
- data/config/application.rb +109 -109
- data/config/commands.rb +74 -74
- data/config/shared_commands.rb +40 -40
- data/config/version.rb +8 -8
- data/lib/origen_link.rb +4 -4
- data/lib/origen_link/callback_handlers.rb +13 -13
- data/lib/origen_link/capture_support.rb +94 -94
- data/lib/origen_link/configuration_commands.rb +84 -84
- data/lib/origen_link/listener.rb +78 -78
- data/lib/origen_link/server/jtag.rb +180 -180
- data/lib/origen_link/server/pin.rb +121 -121
- data/lib/origen_link/server/sequencer.rb +361 -361
- data/lib/origen_link/server_com.rb +150 -150
- data/lib/origen_link/test/top_level.rb +48 -48
- data/lib/origen_link/test/top_level_controller.rb +44 -44
- data/lib/origen_link/test/vector_based.rb +25 -25
- data/lib/origen_link/vector_based.rb +366 -365
- data/lib/tasks/origen_link.rake +6 -6
- data/pattern/example.rb +4 -4
- data/pattern/jtag_capture_id.rb +22 -22
- data/pattern/transaction_test.rb +18 -18
- data/templates/web/index.md.erb +25 -25
- data/templates/web/layouts/_basic.html.erb +13 -13
- data/templates/web/partials/_navbar.html.erb +20 -20
- data/templates/web/release_notes.md.erb +5 -5
- metadata +3 -4
data/config/shared_commands.rb
CHANGED
@@ -1,40 +1,40 @@
|
|
1
|
-
# The requested command is passed in here as @command
|
2
|
-
case @command
|
3
|
-
|
4
|
-
when "link:listen"
|
5
|
-
t = Thread.new do
|
6
|
-
OrigenLink::Listener.run!
|
7
|
-
end
|
8
|
-
Thread.new do
|
9
|
-
# Get the current host
|
10
|
-
host = `hostname`.strip.downcase
|
11
|
-
if Origen.os.windows?
|
12
|
-
domain = '' # Not sure what to do in this case...
|
13
|
-
else
|
14
|
-
domain = `dnsdomainname`.strip
|
15
|
-
end
|
16
|
-
port = 20020
|
17
|
-
puts ''
|
18
|
-
sleep 0.5
|
19
|
-
puts
|
20
|
-
puts
|
21
|
-
puts "*************************************************************"
|
22
|
-
puts "Point your OrigenLink app to: http://#{host}#{domain.empty? ? '' : '.' + domain}:#{port}"
|
23
|
-
puts "*************************************************************"
|
24
|
-
puts
|
25
|
-
puts
|
26
|
-
end
|
27
|
-
|
28
|
-
# Fall through to the Origen interactive command to open up a console
|
29
|
-
@command = "interactive"
|
30
|
-
|
31
|
-
# Always leave an else clause to allow control to fall back through to the Origen command handler.
|
32
|
-
# You probably want to also add the command details to the help shown via 'origen -h',
|
33
|
-
# you can do this bb adding the required text to @plugin_commands before handing control back to
|
34
|
-
# Origen.
|
35
|
-
else
|
36
|
-
@plugin_commands << <<-EOT
|
37
|
-
link:listen Open a console and listen for OrigenLink requests over http (i.e. from a GUI)
|
38
|
-
EOT
|
39
|
-
|
40
|
-
end
|
1
|
+
# The requested command is passed in here as @command
|
2
|
+
case @command
|
3
|
+
|
4
|
+
when "link:listen"
|
5
|
+
t = Thread.new do
|
6
|
+
OrigenLink::Listener.run!
|
7
|
+
end
|
8
|
+
Thread.new do
|
9
|
+
# Get the current host
|
10
|
+
host = `hostname`.strip.downcase
|
11
|
+
if Origen.os.windows?
|
12
|
+
domain = '' # Not sure what to do in this case...
|
13
|
+
else
|
14
|
+
domain = `dnsdomainname`.strip
|
15
|
+
end
|
16
|
+
port = 20020
|
17
|
+
puts ''
|
18
|
+
sleep 0.5
|
19
|
+
puts
|
20
|
+
puts
|
21
|
+
puts "*************************************************************"
|
22
|
+
puts "Point your OrigenLink app to: http://#{host}#{domain.empty? ? '' : '.' + domain}:#{port}"
|
23
|
+
puts "*************************************************************"
|
24
|
+
puts
|
25
|
+
puts
|
26
|
+
end
|
27
|
+
|
28
|
+
# Fall through to the Origen interactive command to open up a console
|
29
|
+
@command = "interactive"
|
30
|
+
|
31
|
+
# Always leave an else clause to allow control to fall back through to the Origen command handler.
|
32
|
+
# You probably want to also add the command details to the help shown via 'origen -h',
|
33
|
+
# you can do this bb adding the required text to @plugin_commands before handing control back to
|
34
|
+
# Origen.
|
35
|
+
else
|
36
|
+
@plugin_commands << <<-EOT
|
37
|
+
link:listen Open a console and listen for OrigenLink requests over http (i.e. from a GUI)
|
38
|
+
EOT
|
39
|
+
|
40
|
+
end
|
data/config/version.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
module OrigenLink
|
2
|
-
MAJOR = 0
|
3
|
-
MINOR = 2
|
4
|
-
BUGFIX = 0
|
5
|
-
DEV =
|
6
|
-
|
7
|
-
VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
|
8
|
-
end
|
1
|
+
module OrigenLink
|
2
|
+
MAJOR = 0
|
3
|
+
MINOR = 2
|
4
|
+
BUGFIX = 0
|
5
|
+
DEV = nil
|
6
|
+
|
7
|
+
VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
|
8
|
+
end
|
data/lib/origen_link.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'origen'
|
2
|
-
require 'socket'
|
3
|
-
require 'origen_link/vector_based'
|
4
|
-
require 'origen_link/listener'
|
1
|
+
require 'origen'
|
2
|
+
require 'socket'
|
3
|
+
require 'origen_link/vector_based'
|
4
|
+
require 'origen_link/listener'
|
@@ -1,13 +1,13 @@
|
|
1
|
-
module OrigenLink
|
2
|
-
class CallbackHandlers
|
3
|
-
include Origen::Callbacks
|
4
|
-
|
5
|
-
def pattern_generated(output_file)
|
6
|
-
tester.finalize_pattern(output_file)
|
7
|
-
end
|
8
|
-
|
9
|
-
def before_pattern(pattern_name)
|
10
|
-
tester.initialize_pattern
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
1
|
+
module OrigenLink
|
2
|
+
class CallbackHandlers
|
3
|
+
include Origen::Callbacks
|
4
|
+
|
5
|
+
def pattern_generated(output_file)
|
6
|
+
tester.finalize_pattern(output_file)
|
7
|
+
end
|
8
|
+
|
9
|
+
def before_pattern(pattern_name)
|
10
|
+
tester.initialize_pattern
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,94 +1,94 @@
|
|
1
|
-
module OrigenLink
|
2
|
-
module CaptureSupport
|
3
|
-
# Capture a vector
|
4
|
-
#
|
5
|
-
# This method applies a store vector request to the previous vector, note that is does
|
6
|
-
# not actually generate a new vector.
|
7
|
-
#
|
8
|
-
# The captured data is added to the captured_data array.
|
9
|
-
#
|
10
|
-
# This method is indended to be used by pin drivers, see the #capture method for the application
|
11
|
-
# level API.
|
12
|
-
#
|
13
|
-
# @example
|
14
|
-
# $tester.cycle # This is the vector you want to capture
|
15
|
-
# $tester.store # This applies the store request
|
16
|
-
def store(*pins)
|
17
|
-
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
18
|
-
fail 'The store is not implemented yet on Link'
|
19
|
-
end
|
20
|
-
|
21
|
-
# Capture the next vector generated
|
22
|
-
#
|
23
|
-
# This method applies a store request to the next vector to be generated,
|
24
|
-
# note that is does not actually generate a new vector.
|
25
|
-
#
|
26
|
-
# The captured data is added to the captured_data array.
|
27
|
-
#
|
28
|
-
# This method is indended to be used by pin drivers, see the #capture method for the application
|
29
|
-
# level API.
|
30
|
-
#
|
31
|
-
# @example
|
32
|
-
# tester.store_next_cycle
|
33
|
-
# tester.cycle # This is the vector that will be captured
|
34
|
-
def store_next_cycle(*pins)
|
35
|
-
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
36
|
-
flush_vector
|
37
|
-
@store_pins = pins
|
38
|
-
end
|
39
|
-
|
40
|
-
# Capture any store data within the given block, return it and then internally clear the tester's
|
41
|
-
# capture memory.
|
42
|
-
#
|
43
|
-
# @example
|
44
|
-
#
|
45
|
-
# v = tester.capture do
|
46
|
-
# my_reg.store!
|
47
|
-
# end
|
48
|
-
# v # => Data value read from my_reg on the DUT
|
49
|
-
def capture(*args)
|
50
|
-
if block_given?
|
51
|
-
yield
|
52
|
-
synchronize
|
53
|
-
d = @captured_data
|
54
|
-
@captured_data = []
|
55
|
-
d
|
56
|
-
else
|
57
|
-
# On other testers capture is an alias of store
|
58
|
-
store(*args)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
def capture_data(response)
|
65
|
-
if @store_pins.size > 1
|
66
|
-
fail 'Data capture on multiple pins is not implemented yet'
|
67
|
-
else
|
68
|
-
captured_data[0] ||= 0
|
69
|
-
captured_data[0] = (captured_data[0] << 1) | extract_value(response, @store_pins[0])
|
70
|
-
@store_pins = []
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def extract_value(response, pin)
|
75
|
-
v = response[index_of(pin) + 2]
|
76
|
-
if v == '`'
|
77
|
-
1
|
78
|
-
elsif v == '.'
|
79
|
-
0
|
80
|
-
else
|
81
|
-
fail "Failed to extract value for pin #{pin.name}, character in response is: #{v}"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
# Returns the vector index (position) of the given pin
|
86
|
-
def index_of(pin)
|
87
|
-
i = @pinorder.split(',').index(pin.name.to_s)
|
88
|
-
unless i
|
89
|
-
fail "Data capture of pin #{pin.name} has been requested, but it has not been included in the Link pinmap!"
|
90
|
-
end
|
91
|
-
i
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
1
|
+
module OrigenLink
|
2
|
+
module CaptureSupport
|
3
|
+
# Capture a vector
|
4
|
+
#
|
5
|
+
# This method applies a store vector request to the previous vector, note that is does
|
6
|
+
# not actually generate a new vector.
|
7
|
+
#
|
8
|
+
# The captured data is added to the captured_data array.
|
9
|
+
#
|
10
|
+
# This method is indended to be used by pin drivers, see the #capture method for the application
|
11
|
+
# level API.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# $tester.cycle # This is the vector you want to capture
|
15
|
+
# $tester.store # This applies the store request
|
16
|
+
def store(*pins)
|
17
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
18
|
+
fail 'The store is not implemented yet on Link'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Capture the next vector generated
|
22
|
+
#
|
23
|
+
# This method applies a store request to the next vector to be generated,
|
24
|
+
# note that is does not actually generate a new vector.
|
25
|
+
#
|
26
|
+
# The captured data is added to the captured_data array.
|
27
|
+
#
|
28
|
+
# This method is indended to be used by pin drivers, see the #capture method for the application
|
29
|
+
# level API.
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# tester.store_next_cycle
|
33
|
+
# tester.cycle # This is the vector that will be captured
|
34
|
+
def store_next_cycle(*pins)
|
35
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
36
|
+
flush_vector
|
37
|
+
@store_pins = pins
|
38
|
+
end
|
39
|
+
|
40
|
+
# Capture any store data within the given block, return it and then internally clear the tester's
|
41
|
+
# capture memory.
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
#
|
45
|
+
# v = tester.capture do
|
46
|
+
# my_reg.store!
|
47
|
+
# end
|
48
|
+
# v # => Data value read from my_reg on the DUT
|
49
|
+
def capture(*args)
|
50
|
+
if block_given?
|
51
|
+
yield
|
52
|
+
synchronize
|
53
|
+
d = @captured_data
|
54
|
+
@captured_data = []
|
55
|
+
d
|
56
|
+
else
|
57
|
+
# On other testers capture is an alias of store
|
58
|
+
store(*args)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def capture_data(response)
|
65
|
+
if @store_pins.size > 1
|
66
|
+
fail 'Data capture on multiple pins is not implemented yet'
|
67
|
+
else
|
68
|
+
captured_data[0] ||= 0
|
69
|
+
captured_data[0] = (captured_data[0] << 1) | extract_value(response, @store_pins[0])
|
70
|
+
@store_pins = []
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def extract_value(response, pin)
|
75
|
+
v = response[index_of(pin) + 2]
|
76
|
+
if v == '`'
|
77
|
+
1
|
78
|
+
elsif v == '.'
|
79
|
+
0
|
80
|
+
else
|
81
|
+
fail "Failed to extract value for pin #{pin.name}, character in response is: #{v}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns the vector index (position) of the given pin
|
86
|
+
def index_of(pin)
|
87
|
+
i = @pinorder.split(',').index(pin.name.to_s)
|
88
|
+
unless i
|
89
|
+
fail "Data capture of pin #{pin.name} has been requested, but it has not been included in the Link pinmap!"
|
90
|
+
end
|
91
|
+
i
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -1,84 +1,84 @@
|
|
1
|
-
module OrigenLink
|
2
|
-
module ConfigurationCommands
|
3
|
-
# pinmap=
|
4
|
-
# This method is used to setup the pin map on the debugger device.
|
5
|
-
# The argument should be a string with <pin name>, <gpio #>, <pin name>
|
6
|
-
# <gpio #>, etc
|
7
|
-
#
|
8
|
-
# example:
|
9
|
-
# tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
|
10
|
-
def pinmap=(pinmap)
|
11
|
-
@pinmap = pinmap.gsub(/\s+/, '')
|
12
|
-
response = send_cmd('pin_assign', @pinmap)
|
13
|
-
setup_cmd_response_logger('pin_assign', response)
|
14
|
-
end
|
15
|
-
|
16
|
-
# pinorder=
|
17
|
-
# This method is used to setup the pin order on the debugger device.
|
18
|
-
# The pin order will indicate the order that pin data appears in vector
|
19
|
-
# data.
|
20
|
-
#
|
21
|
-
# This is a duplicate of pattern_pin_order and can be handled behind the
|
22
|
-
# scenes in the future.
|
23
|
-
#
|
24
|
-
# example:
|
25
|
-
# tester.pinorder = 'tclk,tms,tdi,tdo'
|
26
|
-
def pinorder=(pinorder)
|
27
|
-
@pinorder = pinorder.gsub(/\s+/, '')
|
28
|
-
response = send_cmd('pin_patternorder', @pinorder)
|
29
|
-
setup_cmd_response_logger('pin_patternorder', response)
|
30
|
-
end
|
31
|
-
|
32
|
-
# pinformat=
|
33
|
-
# This method is used to setup the pin clock format on the debugger device.
|
34
|
-
# The supported formats are rl and rh
|
35
|
-
#
|
36
|
-
# example:
|
37
|
-
# tester.pinformat = 'func_25mhz,tclk,rl'
|
38
|
-
def pinformat=(pinformat)
|
39
|
-
@pinformat = replace_tset_name_w_number(pinformat.gsub(/\s+/, ''))
|
40
|
-
response = send_cmd('pin_format', @pinformat)
|
41
|
-
setup_cmd_response_logger('pin_format', response)
|
42
|
-
end
|
43
|
-
|
44
|
-
# pintiming=
|
45
|
-
# This method is used to setup the pin timing on the debugger device.
|
46
|
-
# Timing is relative to the rise and fall of a clock
|
47
|
-
#
|
48
|
-
# timing value: 0 1 2
|
49
|
-
# clock waveform: ___/***\___
|
50
|
-
#
|
51
|
-
# example:
|
52
|
-
# tester.pintiming = 'func_25mhz,tms,0,tdi,0,tdo,1'
|
53
|
-
def pintiming=(pintiming)
|
54
|
-
@pintiming = replace_tset_name_w_number(pintiming.gsub(/\s+/, ''))
|
55
|
-
response = send_cmd('pin_timing', @pintiming)
|
56
|
-
setup_cmd_response_logger('pin_timing', response)
|
57
|
-
end
|
58
|
-
|
59
|
-
# replace_tset_name_w_number(csl)
|
60
|
-
# This method is used by pinformat= and pintiming=
|
61
|
-
# This method receives a comma separated list of arguments
|
62
|
-
# the first of which is a timeset name. A comma
|
63
|
-
# separated list is returned with the timeset name replaced
|
64
|
-
# by it's lookup number. If it is a new timset, a lookup
|
65
|
-
# number is associated with the name.
|
66
|
-
def replace_tset_name_w_number(csl)
|
67
|
-
args = csl.split(',')
|
68
|
-
args[0] = get_tset_number(args[0])
|
69
|
-
args.join(',')
|
70
|
-
end
|
71
|
-
|
72
|
-
# get_tset_number(name)
|
73
|
-
# This method returns the test number associated with the
|
74
|
-
# passed in tset name. If the name is unknown a new lookup
|
75
|
-
# number is returned.
|
76
|
-
def get_tset_number(name)
|
77
|
-
unless @tsets_programmed.key?(name)
|
78
|
-
@tsets_programmed[name] = @tset_count
|
79
|
-
@tset_count += 1
|
80
|
-
end
|
81
|
-
@tsets_programmed[name]
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
1
|
+
module OrigenLink
|
2
|
+
module ConfigurationCommands
|
3
|
+
# pinmap=
|
4
|
+
# This method is used to setup the pin map on the debugger device.
|
5
|
+
# The argument should be a string with <pin name>, <gpio #>, <pin name>
|
6
|
+
# <gpio #>, etc
|
7
|
+
#
|
8
|
+
# example:
|
9
|
+
# tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
|
10
|
+
def pinmap=(pinmap)
|
11
|
+
@pinmap = pinmap.gsub(/\s+/, '')
|
12
|
+
response = send_cmd('pin_assign', @pinmap)
|
13
|
+
setup_cmd_response_logger('pin_assign', response)
|
14
|
+
end
|
15
|
+
|
16
|
+
# pinorder=
|
17
|
+
# This method is used to setup the pin order on the debugger device.
|
18
|
+
# The pin order will indicate the order that pin data appears in vector
|
19
|
+
# data.
|
20
|
+
#
|
21
|
+
# This is a duplicate of pattern_pin_order and can be handled behind the
|
22
|
+
# scenes in the future.
|
23
|
+
#
|
24
|
+
# example:
|
25
|
+
# tester.pinorder = 'tclk,tms,tdi,tdo'
|
26
|
+
def pinorder=(pinorder)
|
27
|
+
@pinorder = pinorder.gsub(/\s+/, '')
|
28
|
+
response = send_cmd('pin_patternorder', @pinorder)
|
29
|
+
setup_cmd_response_logger('pin_patternorder', response)
|
30
|
+
end
|
31
|
+
|
32
|
+
# pinformat=
|
33
|
+
# This method is used to setup the pin clock format on the debugger device.
|
34
|
+
# The supported formats are rl and rh
|
35
|
+
#
|
36
|
+
# example:
|
37
|
+
# tester.pinformat = 'func_25mhz,tclk,rl'
|
38
|
+
def pinformat=(pinformat)
|
39
|
+
@pinformat = replace_tset_name_w_number(pinformat.gsub(/\s+/, ''))
|
40
|
+
response = send_cmd('pin_format', @pinformat)
|
41
|
+
setup_cmd_response_logger('pin_format', response)
|
42
|
+
end
|
43
|
+
|
44
|
+
# pintiming=
|
45
|
+
# This method is used to setup the pin timing on the debugger device.
|
46
|
+
# Timing is relative to the rise and fall of a clock
|
47
|
+
#
|
48
|
+
# timing value: 0 1 2
|
49
|
+
# clock waveform: ___/***\___
|
50
|
+
#
|
51
|
+
# example:
|
52
|
+
# tester.pintiming = 'func_25mhz,tms,0,tdi,0,tdo,1'
|
53
|
+
def pintiming=(pintiming)
|
54
|
+
@pintiming = replace_tset_name_w_number(pintiming.gsub(/\s+/, ''))
|
55
|
+
response = send_cmd('pin_timing', @pintiming)
|
56
|
+
setup_cmd_response_logger('pin_timing', response)
|
57
|
+
end
|
58
|
+
|
59
|
+
# replace_tset_name_w_number(csl)
|
60
|
+
# This method is used by pinformat= and pintiming=
|
61
|
+
# This method receives a comma separated list of arguments
|
62
|
+
# the first of which is a timeset name. A comma
|
63
|
+
# separated list is returned with the timeset name replaced
|
64
|
+
# by it's lookup number. If it is a new timset, a lookup
|
65
|
+
# number is associated with the name.
|
66
|
+
def replace_tset_name_w_number(csl)
|
67
|
+
args = csl.split(',')
|
68
|
+
args[0] = get_tset_number(args[0])
|
69
|
+
args.join(',')
|
70
|
+
end
|
71
|
+
|
72
|
+
# get_tset_number(name)
|
73
|
+
# This method returns the test number associated with the
|
74
|
+
# passed in tset name. If the name is unknown a new lookup
|
75
|
+
# number is returned.
|
76
|
+
def get_tset_number(name)
|
77
|
+
unless @tsets_programmed.key?(name)
|
78
|
+
@tsets_programmed[name] = @tset_count
|
79
|
+
@tset_count += 1
|
80
|
+
end
|
81
|
+
@tsets_programmed[name]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|