origen_link 0.1.0 → 0.1.2
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/config/version.rb +1 -1
- data/lib/origen_link/capture_support.rb +94 -0
- data/lib/origen_link/configuration_commands.rb +84 -0
- data/lib/origen_link/server/sequencer.rb +14 -6
- data/lib/origen_link/server_com.rb +2 -0
- data/lib/origen_link/test/top_level_controller.rb +11 -11
- data/lib/origen_link/vector_based.rb +81 -177
- data/pattern/jtag_100_operations.rb +1 -1
- data/pattern/jtag_capture_id.rb +23 -0
- data/pattern/transaction_test.rb +19 -0
- metadata +7 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7b819630a6b626e6c330114c40f70108f7850657
         | 
| 4 | 
            +
              data.tar.gz: 51a6ddf9796af5b1569c3b61a9e8f8d2b3c955c9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 379e3b256c9becd833c2d2fd76fcfba2c3b1b7c3f4922986e6ca8523eb0bda24919366189c06695577aea979be102a7a2a0fb84e4b8f55973d22cd14927b6117
         | 
| 7 | 
            +
              data.tar.gz: 222fdaf6916110972cacb9a25f1f2cf0b60ba8406770f8518f8777b00e771c1755eff011ecc46465c4dac7f5035e5ff19eb57ed8dd1a4acf60a423d4db174941
         | 
    
        data/config/version.rb
    CHANGED
    
    
| @@ -0,0 +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
         | 
| @@ -0,0 +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
         | 
| @@ -264,11 +264,17 @@ module OrigenLink | |
| 264 264 | 
             
                      end
         | 
| 265 265 | 
             
                      # process time 2 events
         | 
| 266 266 | 
             
                      response = process_events(@cycletiming[tset]['timing'][2], pindata).merge(response)
         | 
| 267 | 
            -
                       | 
| 268 | 
            -
             | 
| 269 | 
            -
             | 
| 270 | 
            -
             | 
| 271 | 
            -
             | 
| 267 | 
            +
                      # changing response format to return all data for easier debug, below is original method
         | 
| 268 | 
            +
                      # TODO: remove the commented code once return format and delay handling is finalized
         | 
| 269 | 
            +
                      # if (count == 0) || (@cycle_failure)
         | 
| 270 | 
            +
                      #  message = ''
         | 
| 271 | 
            +
                      #  @patternorder.each do |pin|
         | 
| 272 | 
            +
                      #    message += response[pin]
         | 
| 273 | 
            +
                      #  end
         | 
| 274 | 
            +
                      # end
         | 
| 275 | 
            +
                      message = message + ' ' unless count == 0
         | 
| 276 | 
            +
                      @patternorder.each do |pin|
         | 
| 277 | 
            +
                        message += response[pin]
         | 
| 272 278 | 
             
                      end
         | 
| 273 279 | 
             
                    end # end cycle through repeats
         | 
| 274 280 | 
             
                    if @cycle_failure
         | 
| @@ -276,7 +282,9 @@ module OrigenLink | |
| 276 282 | 
             
                    else
         | 
| 277 283 | 
             
                      rtnmsg = 'P:' + message
         | 
| 278 284 | 
             
                    end
         | 
| 279 | 
            -
                     | 
| 285 | 
            +
                    # no need to return repeat count since all data is returned
         | 
| 286 | 
            +
                    # TODO: remove the commented code once return format and delay handling is finalized
         | 
| 287 | 
            +
                    # rtnmsg += '    Repeat ' + repeat_count.to_s if repeat_count > 1
         | 
| 280 288 | 
             
                    rtnmsg
         | 
| 281 289 | 
             
                  end
         | 
| 282 290 |  | 
| @@ -45,6 +45,7 @@ module OrigenLink | |
| 45 45 | 
             
                  @max_receive_time = (t4 - t3) if @max_receive_time < (t4 - t3)
         | 
| 46 46 | 
             
                  @total_packets += 1
         | 
| 47 47 | 
             
                  Origen.log.error 'nil response from server (likely died) for command(' + cmdstr + ':' + argstr + ')' if response.nil?
         | 
| 48 | 
            +
                  @pattern_link_messages << "#{cmdstr}:#{argstr}"
         | 
| 48 49 | 
             
                  response    # ensure the response is passed along
         | 
| 49 50 | 
             
                end
         | 
| 50 51 |  | 
| @@ -72,6 +73,7 @@ module OrigenLink | |
| 72 73 | 
             
                  @total_recv_time += (t4 - t3)
         | 
| 73 74 | 
             
                  @max_receive_time = (t4 - t3) if @max_receive_time < (t4 - t3)
         | 
| 74 75 | 
             
                  @total_packets += 1
         | 
| 76 | 
            +
                  @pattern_link_messages.concat(vector_batch)
         | 
| 75 77 | 
             
                  response
         | 
| 76 78 | 
             
                end
         | 
| 77 79 |  | 
| @@ -6,23 +6,23 @@ module OrigenLink | |
| 6 6 | 
             
                  include OrigenJTAG
         | 
| 7 7 |  | 
| 8 8 | 
             
                  JTAG_CONFIG = {
         | 
| 9 | 
            -
                     | 
| 10 | 
            -
                    tclk_format:     :rh,
         | 
| 11 | 
            -
                     | 
| 12 | 
            -
                    tclk_multiple:   4,
         | 
| 13 | 
            -
                    tdo_strobe: | 
| 14 | 
            -
                    tdo_store_cycle: 3,
         | 
| 15 | 
            -
                    init_state: | 
| 9 | 
            +
                    tclk_format:	  :rl,
         | 
| 10 | 
            +
                    # tclk_format:     :rh,
         | 
| 11 | 
            +
                    tclk_multiple:	1,
         | 
| 12 | 
            +
                    # tclk_multiple:   4,
         | 
| 13 | 
            +
                    tdo_strobe:    :tclk_high,
         | 
| 14 | 
            +
                    # tdo_store_cycle: 3,
         | 
| 15 | 
            +
                    init_state:    :idle
         | 
| 16 16 | 
             
                  }
         | 
| 17 17 |  | 
| 18 18 | 
             
                  def startup(options)
         | 
| 19 19 | 
             
                    pp 'Enter test mode' do
         | 
| 20 20 | 
             
                      # if tester.link?
         | 
| 21 21 | 
             
                      if tester.to_s == 'OrigenLink::VectorBased'
         | 
| 22 | 
            -
                        tester.initialize_pattern
         | 
| 22 | 
            +
                        # tester.initialize_pattern
         | 
| 23 23 | 
             
                        # below is for testing return format timing, requires tclk to be rl and multiple of 1
         | 
| 24 | 
            -
                         | 
| 25 | 
            -
                         | 
| 24 | 
            +
                        tester.pinformat = 'func_25mhz,tclk,rl'
         | 
| 25 | 
            +
                        tester.pintiming = 'func_25mhz,tdi,0,tms,0,tdo,1'
         | 
| 26 26 | 
             
                      end
         | 
| 27 27 | 
             
                      tester.set_timeset('func_25mhz', 40)   # Where 40 is the period in ns
         | 
| 28 28 | 
             
                      tester.wait time_in_us: 100
         | 
| @@ -36,7 +36,7 @@ module OrigenLink | |
| 36 36 | 
             
                    end
         | 
| 37 37 | 
             
                    # if tester.link?
         | 
| 38 38 | 
             
                    if tester.to_s == 'OrigenLink::VectorBased'
         | 
| 39 | 
            -
                      tester.finalize_pattern
         | 
| 39 | 
            +
                      # tester.finalize_pattern
         | 
| 40 40 | 
             
                    end
         | 
| 41 41 | 
             
                  end
         | 
| 42 42 | 
             
                end
         | 
| @@ -1,5 +1,7 @@ | |
| 1 1 | 
             
            require 'origen_testers'
         | 
| 2 2 | 
             
            require 'origen_link/server_com'
         | 
| 3 | 
            +
            require 'origen_link/capture_support'
         | 
| 4 | 
            +
            require 'origen_link/configuration_commands'
         | 
| 3 5 | 
             
            require 'origen_link/callback_handlers'
         | 
| 4 6 | 
             
            module OrigenLink
         | 
| 5 7 | 
             
              # OrigenLink::VectorBased
         | 
| @@ -30,6 +32,8 @@ module OrigenLink | |
| 30 32 | 
             
              class VectorBased
         | 
| 31 33 | 
             
                include OrigenTesters::VectorBasedTester
         | 
| 32 34 | 
             
                include ServerCom
         | 
| 35 | 
            +
                include CaptureSupport
         | 
| 36 | 
            +
                include ConfigurationCommands
         | 
| 33 37 |  | 
| 34 38 | 
             
                # these attributes are exposed for testing purposes, a user would not need to read them
         | 
| 35 39 | 
             
                attr_reader :fail_count, :vector_count, :total_comm_time, :total_connect_time, :total_xmit_time
         | 
| @@ -62,6 +66,8 @@ module OrigenLink | |
| 62 66 | 
             
                  @store_pins_batch = {}
         | 
| 63 67 | 
             
                  @comment_batch = {}
         | 
| 64 68 | 
             
                  @batch_vectors = true
         | 
| 69 | 
            +
                  @pattern_link_messages = []
         | 
| 70 | 
            +
                  @pattern_comments = {}
         | 
| 65 71 | 
             
                end
         | 
| 66 72 |  | 
| 67 73 | 
             
                # push_comment
         | 
| @@ -75,6 +81,8 @@ module OrigenLink | |
| 75 81 | 
             
                    else
         | 
| 76 82 | 
             
                      @comment_batch[key] = msg
         | 
| 77 83 | 
             
                    end
         | 
| 84 | 
            +
                    pattern_key = @pattern_link_messages.length + key
         | 
| 85 | 
            +
                    @pattern_comments[pattern_key] = @comment_batch[key]
         | 
| 78 86 | 
             
                  else
         | 
| 79 87 | 
             
                    microcode msg
         | 
| 80 88 | 
             
                  end
         | 
| @@ -111,65 +119,6 @@ module OrigenLink | |
| 111 119 | 
             
                  @vector_count += 1
         | 
| 112 120 | 
             
                end
         | 
| 113 121 |  | 
| 114 | 
            -
                # Capture a vector
         | 
| 115 | 
            -
                #
         | 
| 116 | 
            -
                # This method applies a store vector request to the previous vector, note that is does
         | 
| 117 | 
            -
                # not actually generate a new vector.
         | 
| 118 | 
            -
                #
         | 
| 119 | 
            -
                # The captured data is added to the captured_data array.
         | 
| 120 | 
            -
                #
         | 
| 121 | 
            -
                # This method is indended to be used by pin drivers, see the #capture method for the application
         | 
| 122 | 
            -
                # level API.
         | 
| 123 | 
            -
                #
         | 
| 124 | 
            -
                # @example
         | 
| 125 | 
            -
                #   $tester.cycle                # This is the vector you want to capture
         | 
| 126 | 
            -
                #   $tester.store                # This applies the store request
         | 
| 127 | 
            -
                def store(*pins)
         | 
| 128 | 
            -
                  options = pins.last.is_a?(Hash) ? pins.pop : {}
         | 
| 129 | 
            -
                  fail 'The store is not implemented yet on Link'
         | 
| 130 | 
            -
                end
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                # Capture the next vector generated
         | 
| 133 | 
            -
                #
         | 
| 134 | 
            -
                # This method applies a store request to the next vector to be generated,
         | 
| 135 | 
            -
                # note that is does not actually generate a new vector.
         | 
| 136 | 
            -
                #
         | 
| 137 | 
            -
                # The captured data is added to the captured_data array.
         | 
| 138 | 
            -
                #
         | 
| 139 | 
            -
                # This method is indended to be used by pin drivers, see the #capture method for the application
         | 
| 140 | 
            -
                # level API.
         | 
| 141 | 
            -
                #
         | 
| 142 | 
            -
                # @example
         | 
| 143 | 
            -
                #   tester.store_next_cycle
         | 
| 144 | 
            -
                #   tester.cycle                # This is the vector that will be captured
         | 
| 145 | 
            -
                def store_next_cycle(*pins)
         | 
| 146 | 
            -
                  options = pins.last.is_a?(Hash) ? pins.pop : {}
         | 
| 147 | 
            -
                  flush_vector
         | 
| 148 | 
            -
                  @store_pins = pins
         | 
| 149 | 
            -
                end
         | 
| 150 | 
            -
             | 
| 151 | 
            -
                # Capture any store data within the given block, return it and then internally clear the tester's
         | 
| 152 | 
            -
                # capture memory.
         | 
| 153 | 
            -
                #
         | 
| 154 | 
            -
                # @example
         | 
| 155 | 
            -
                #
         | 
| 156 | 
            -
                #   v = tester.capture do
         | 
| 157 | 
            -
                #     my_reg.store!
         | 
| 158 | 
            -
                #   end
         | 
| 159 | 
            -
                #   v      # => Data value read from my_reg on the DUT
         | 
| 160 | 
            -
                def capture(*args)
         | 
| 161 | 
            -
                  if block_given?
         | 
| 162 | 
            -
                    yield
         | 
| 163 | 
            -
                    synchronize
         | 
| 164 | 
            -
                    d = @captured_data
         | 
| 165 | 
            -
                    @captured_data = []
         | 
| 166 | 
            -
                    d
         | 
| 167 | 
            -
                  else
         | 
| 168 | 
            -
                    # On other testers capture is an alias of store
         | 
| 169 | 
            -
                    store(*args)
         | 
| 170 | 
            -
                  end
         | 
| 171 | 
            -
                end
         | 
| 172 | 
            -
             | 
| 173 122 | 
             
                # flush_vector
         | 
| 174 123 | 
             
                #   Just as the name suggests, this method "flushes" a vector.  This is necessary because
         | 
| 175 124 | 
             
                #   of repeat compression (a vector isn't sent until different vector data is encountered)
         | 
| @@ -230,6 +179,10 @@ module OrigenLink | |
| 230 179 | 
             
                    # if called from finalize_pattern -> synchronize, open the output_file and store results
         | 
| 231 180 | 
             
                    output_obj = nil
         | 
| 232 181 | 
             
                    output_obj = File.open(output_file, 'a+') unless output_file == ''
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                    # in case there were only comments and no vectors, place comments (if any)
         | 
| 184 | 
            +
                    microcode @comment_batch[0] if response.size == 0
         | 
| 185 | 
            +
             | 
| 233 186 | 
             
                    response.each_index do |index|
         | 
| 234 187 | 
             
                      # restore store pins state for processing
         | 
| 235 188 | 
             
                      if @store_pins_batch.key?(index)
         | 
| @@ -237,17 +190,19 @@ module OrigenLink | |
| 237 190 | 
             
                      else
         | 
| 238 191 | 
             
                        @store_pins = []
         | 
| 239 192 | 
             
                      end
         | 
| 193 | 
            +
                      process_vector_response(response[index], output_obj)
         | 
| 240 194 | 
             
                      if @comment_batch.key?(index)
         | 
| 241 | 
            -
                         | 
| 242 | 
            -
                           | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
             | 
| 246 | 
            -
                           | 
| 195 | 
            +
                        if output_file == ''
         | 
| 196 | 
            +
                          microcode @comment_batch[index]
         | 
| 197 | 
            +
                        else
         | 
| 198 | 
            +
                          # get the header placed correctly, the below code doesn't work
         | 
| 199 | 
            +
                          # if index == response.length - 1
         | 
| 200 | 
            +
                          #   output_obj.puts 'last comment'
         | 
| 201 | 
            +
                          #   output_obj.lineno = 0
         | 
| 202 | 
            +
                          # end
         | 
| 247 203 | 
             
                          output_obj.puts(@comment_batch[index])
         | 
| 248 204 | 
             
                        end
         | 
| 249 205 | 
             
                      end
         | 
| 250 | 
            -
                      process_vector_response(response[index], output_obj)
         | 
| 251 206 | 
             
                    end
         | 
| 252 207 | 
             
                    output_obj.close unless output_file == ''
         | 
| 253 208 | 
             
                  else
         | 
| @@ -265,10 +220,34 @@ module OrigenLink | |
| 265 220 | 
             
                    vector_response.strip!
         | 
| 266 221 | 
             
                    vector_response += msg
         | 
| 267 222 | 
             
                  end
         | 
| 268 | 
            -
                   | 
| 269 | 
            -
             | 
| 270 | 
            -
                   | 
| 271 | 
            -
             | 
| 223 | 
            +
                  vector_cycles = vector_response.split(/\s+/)
         | 
| 224 | 
            +
                  expected_msg = ''
         | 
| 225 | 
            +
                  expected_msg = ' ' + vector_cycles.pop if vector_cycles[vector_cycles.length - 1] =~ /Expected/
         | 
| 226 | 
            +
                  pfstatus = vector_cycles[0].chr
         | 
| 227 | 
            +
                  vector_cycles[0] = vector_cycles[0].byteslice(2, vector_cycles[0].length - 2)
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                  vector_cycles.each do |cycle|
         | 
| 230 | 
            +
                    thiscyclefail = false
         | 
| 231 | 
            +
                    if pfstatus == 'F'
         | 
| 232 | 
            +
                      # check to see if this cycle failed
         | 
| 233 | 
            +
                      0.upto(cycle.length - 1) do |index|
         | 
| 234 | 
            +
                        thiscyclefail = true if (cycle[index] == 'H') && (expected_msg[expected_msg.length - cycle.length + index] == 'L')
         | 
| 235 | 
            +
                        thiscyclefail = true if (cycle[index] == 'L') && (expected_msg[expected_msg.length - cycle.length + index] == 'X')
         | 
| 236 | 
            +
                      end
         | 
| 237 | 
            +
                    end
         | 
| 238 | 
            +
                    if thiscyclefail
         | 
| 239 | 
            +
                      expected_msg_prnt = expected_msg
         | 
| 240 | 
            +
                      prepend = 'F:'
         | 
| 241 | 
            +
                    else
         | 
| 242 | 
            +
                      expected_msg_prnt = ''
         | 
| 243 | 
            +
                      prepend = 'P:'
         | 
| 244 | 
            +
                    end
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                    if output_obj.nil?
         | 
| 247 | 
            +
                      microcode prepend + cycle + expected_msg_prnt
         | 
| 248 | 
            +
                    else
         | 
| 249 | 
            +
                      output_obj.puts(prepend + cycle + expected_msg_prnt)
         | 
| 250 | 
            +
                    end
         | 
| 272 251 | 
             
                  end
         | 
| 273 252 |  | 
| 274 253 | 
             
                  unless vector_response.chr == 'P'
         | 
| @@ -287,6 +266,8 @@ module OrigenLink | |
| 287 266 | 
             
                  @vector_batch.delete_if { true }
         | 
| 288 267 | 
             
                  @store_pins_batch.clear
         | 
| 289 268 | 
             
                  @comment_batch.clear
         | 
| 269 | 
            +
                  @pattern_link_messages.delete_if { true }
         | 
| 270 | 
            +
                  @pattern_comments.clear
         | 
| 290 271 |  | 
| 291 272 | 
             
                  @total_packets = 0
         | 
| 292 273 | 
             
                  @total_comm_time = 0
         | 
| @@ -327,6 +308,15 @@ module OrigenLink | |
| 327 308 | 
             
                    # Origen.log.error("FAIL - pattern execution failed (#{@fail_count} failures)")
         | 
| 328 309 | 
             
                    Origen.app.stats.report_fail
         | 
| 329 310 | 
             
                  end
         | 
| 311 | 
            +
                  commands_file = Origen.app.current_job.output_file.split('.')[0] + '_link_cmds.txt'
         | 
| 312 | 
            +
                  File.open(commands_file, 'w') do |file|
         | 
| 313 | 
            +
                    file.puts("pin_assign:#{@pinmap}")
         | 
| 314 | 
            +
                    file.puts("pin_patternorder:#{@pinorder}")
         | 
| 315 | 
            +
                    @pattern_link_messages.each_index do |index|
         | 
| 316 | 
            +
                      file.puts(@pattern_link_messages[index])
         | 
| 317 | 
            +
                      file.puts(@pattern_comments[index]) if @pattern_comments.key?(index)
         | 
| 318 | 
            +
                    end
         | 
| 319 | 
            +
                  end
         | 
| 330 320 | 
             
                end
         | 
| 331 321 |  | 
| 332 322 | 
             
                # to_s
         | 
| @@ -339,117 +329,31 @@ module OrigenLink | |
| 339 329 | 
             
                  'OrigenLink::VectorBased'
         | 
| 340 330 | 
             
                end
         | 
| 341 331 |  | 
| 342 | 
            -
                #  | 
| 343 | 
            -
                #    | 
| 344 | 
            -
                #    | 
| 345 | 
            -
                #    | 
| 346 | 
            -
                #
         | 
| 347 | 
            -
                #   example:
         | 
| 348 | 
            -
                #     tester.pinmap = 'tclk,26,tms,19,tdi,16,tdo,23'
         | 
| 349 | 
            -
                def pinmap=(pinmap)
         | 
| 350 | 
            -
                  @pinmap = pinmap.gsub(/\s+/, '')
         | 
| 351 | 
            -
                  response = send_cmd('pin_assign', @pinmap)
         | 
| 352 | 
            -
                  setup_cmd_response_logger('pin_assign', response)
         | 
| 353 | 
            -
                end
         | 
| 354 | 
            -
             | 
| 355 | 
            -
                # pinorder=
         | 
| 356 | 
            -
                #   This method is used to setup the pin order on the debugger device.
         | 
| 357 | 
            -
                #   The pin order will indicate the order that pin data appears in vector
         | 
| 358 | 
            -
                #   data.
         | 
| 332 | 
            +
                # transaction
         | 
| 333 | 
            +
                #   returns true/false indicating whether the transaction passed
         | 
| 334 | 
            +
                #   true = pass
         | 
| 335 | 
            +
                #   false = fail
         | 
| 359 336 | 
             
                #
         | 
| 360 | 
            -
                # | 
| 361 | 
            -
                #   scenes in the future.
         | 
| 337 | 
            +
                # TODO: capture transaction vector data and response for use in debug
         | 
| 362 338 | 
             
                #
         | 
| 363 | 
            -
                # | 
| 364 | 
            -
                # | 
| 365 | 
            -
                 | 
| 366 | 
            -
             | 
| 367 | 
            -
                   | 
| 368 | 
            -
             | 
| 369 | 
            -
             | 
| 370 | 
            -
             | 
| 371 | 
            -
             | 
| 372 | 
            -
             | 
| 373 | 
            -
             | 
| 374 | 
            -
             | 
| 375 | 
            -
             | 
| 376 | 
            -
             | 
| 377 | 
            -
             | 
| 378 | 
            -
                  @pinformat = replace_tset_name_w_number(pinformat.gsub(/\s+/, ''))
         | 
| 379 | 
            -
                  response = send_cmd('pin_format', @pinformat)
         | 
| 380 | 
            -
                  setup_cmd_response_logger('pin_format', response)
         | 
| 381 | 
            -
                end
         | 
| 382 | 
            -
             | 
| 383 | 
            -
                # pintiming=
         | 
| 384 | 
            -
                #   This method is used to setup the pin timing on the debugger device.
         | 
| 385 | 
            -
                #   Timing is relative to the rise and fall of a clock
         | 
| 386 | 
            -
                #
         | 
| 387 | 
            -
                #   timing value:         0   1   2
         | 
| 388 | 
            -
                #   clock waveform:      ___/***\___
         | 
| 389 | 
            -
                #
         | 
| 390 | 
            -
                #   example:
         | 
| 391 | 
            -
                #     tester.pintiming = 'func_25mhz,tms,0,tdi,0,tdo,1'
         | 
| 392 | 
            -
                def pintiming=(pintiming)
         | 
| 393 | 
            -
                  @pintiming = replace_tset_name_w_number(pintiming.gsub(/\s+/, ''))
         | 
| 394 | 
            -
                  response = send_cmd('pin_timing', @pintiming)
         | 
| 395 | 
            -
                  setup_cmd_response_logger('pin_timing', response)
         | 
| 396 | 
            -
                end
         | 
| 397 | 
            -
             | 
| 398 | 
            -
                # replace_tset_name_w_number(csl)
         | 
| 399 | 
            -
                #  This method is used by pinformat= and pintiming=
         | 
| 400 | 
            -
                #  This method receives a comma separated list of arguments
         | 
| 401 | 
            -
                #  the first of which is a timeset name.  A comma
         | 
| 402 | 
            -
                #  separated list is returned with the timeset name replaced
         | 
| 403 | 
            -
                #  by it's lookup number.  If it is a new timset, a lookup
         | 
| 404 | 
            -
                #  number is associated with the name.
         | 
| 405 | 
            -
                def replace_tset_name_w_number(csl)
         | 
| 406 | 
            -
                  args = csl.split(',')
         | 
| 407 | 
            -
                  args[0] = get_tset_number(args[0])
         | 
| 408 | 
            -
                  args.join(',')
         | 
| 409 | 
            -
                end
         | 
| 410 | 
            -
             | 
| 411 | 
            -
                # get_tset_number(name)
         | 
| 412 | 
            -
                #   This method returns the test number associated with the
         | 
| 413 | 
            -
                #   passed in tset name.  If the name is unknown a new lookup
         | 
| 414 | 
            -
                #   number is returned.
         | 
| 415 | 
            -
                def get_tset_number(name)
         | 
| 416 | 
            -
                  unless @tsets_programmed.key?(name)
         | 
| 417 | 
            -
                    @tsets_programmed[name] = @tset_count
         | 
| 418 | 
            -
                    @tset_count += 1
         | 
| 419 | 
            -
                  end
         | 
| 420 | 
            -
                  @tsets_programmed[name]
         | 
| 421 | 
            -
                end
         | 
| 422 | 
            -
             | 
| 423 | 
            -
                private
         | 
| 424 | 
            -
             | 
| 425 | 
            -
                def capture_data(response)
         | 
| 426 | 
            -
                  if @store_pins.size > 1
         | 
| 427 | 
            -
                    fail 'Data capture on multiple pins is not implemented yet'
         | 
| 428 | 
            -
                  else
         | 
| 429 | 
            -
                    captured_data[0] ||= 0
         | 
| 430 | 
            -
                    captured_data[0] = (captured_data[0] << 1) | extract_value(response, @store_pins[0])
         | 
| 431 | 
            -
                    @store_pins = []
         | 
| 432 | 
            -
                  end
         | 
| 433 | 
            -
                end
         | 
| 434 | 
            -
             | 
| 435 | 
            -
                def extract_value(response, pin)
         | 
| 436 | 
            -
                  v = response[index_of(pin) + 2]
         | 
| 437 | 
            -
                  if v == '`'
         | 
| 438 | 
            -
                    1
         | 
| 439 | 
            -
                  elsif v == '.'
         | 
| 440 | 
            -
                    0
         | 
| 339 | 
            +
                # if !tester.transaction {dut.reg blah blah}
         | 
| 340 | 
            +
                #   puts 'transaction failed'
         | 
| 341 | 
            +
                # end
         | 
| 342 | 
            +
                def transaction
         | 
| 343 | 
            +
                  if block_given?
         | 
| 344 | 
            +
                    synchronize
         | 
| 345 | 
            +
                    transaction_fail_count = @fail_count
         | 
| 346 | 
            +
                    yield
         | 
| 347 | 
            +
                    synchronize
         | 
| 348 | 
            +
                    transaction_fail_count = @fail_count - transaction_fail_count
         | 
| 349 | 
            +
                    if transaction_fail_count == 0
         | 
| 350 | 
            +
                      true
         | 
| 351 | 
            +
                    else
         | 
| 352 | 
            +
                      false
         | 
| 353 | 
            +
                    end
         | 
| 441 354 | 
             
                  else
         | 
| 442 | 
            -
                     | 
| 443 | 
            -
                  end
         | 
| 444 | 
            -
                end
         | 
| 445 | 
            -
             | 
| 446 | 
            -
                # Returns the vector index (position) of the given pin
         | 
| 447 | 
            -
                def index_of(pin)
         | 
| 448 | 
            -
                  i = @pinorder.split(',').index(pin.name.to_s)
         | 
| 449 | 
            -
                  unless i
         | 
| 450 | 
            -
                    fail "Data capture of pin #{pin.name} has been requested, but it has not been included in the Link pinmap!"
         | 
| 355 | 
            +
                    true
         | 
| 451 356 | 
             
                  end
         | 
| 452 | 
            -
                  i
         | 
| 453 357 | 
             
                end
         | 
| 454 358 | 
             
              end
         | 
| 455 359 | 
             
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            Pattern.create(options={:name => "JTAG_CaptureID"})do
         | 
| 2 | 
            +
              $dut.jtag.reset
         | 
| 3 | 
            +
              $dut.jtag.idle
         | 
| 4 | 
            +
              ss "reading default ID"
         | 
| 5 | 
            +
              $dut.reg(:testreg).bits(31..0).store
         | 
| 6 | 
            +
              default_id = tester.capture {$dut.jtag.read_dr $dut.reg(:testreg), size: 32 }
         | 
| 7 | 
            +
              default_id_str = default_id[0].to_s(2)
         | 
| 8 | 
            +
              default_id_str.reverse!
         | 
| 9 | 
            +
              default_id = default_id_str.to_i(2)
         | 
| 10 | 
            +
              puts '**************************************************'
         | 
| 11 | 
            +
              puts 'Captured default ID through JTAG: 0x' + default_id.to_s(16)
         | 
| 12 | 
            +
              puts '**************************************************'
         | 
| 13 | 
            +
              $dut.jtag.write_ir 0, size: 4
         | 
| 14 | 
            +
              ss "reading JTAG ID"
         | 
| 15 | 
            +
              $dut.reg(:testreg).bits(31..0).store
         | 
| 16 | 
            +
              jtag_id = tester.capture {$dut.jtag.read_dr $dut.reg(:testreg), size: 32 }
         | 
| 17 | 
            +
              jtag_id_str = jtag_id[0].to_s(2)
         | 
| 18 | 
            +
              jtag_id_str.reverse!
         | 
| 19 | 
            +
              jtag_id = jtag_id_str.to_i(2)
         | 
| 20 | 
            +
              puts '**************************************************'
         | 
| 21 | 
            +
              puts 'Captured JTAG ID: 0x' + jtag_id.to_s(16)
         | 
| 22 | 
            +
              puts '**************************************************'
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            Pattern.create(options={:name => "transaction_test"})do
         | 
| 2 | 
            +
              $dut.jtag.reset
         | 
| 3 | 
            +
              $dut.jtag.idle
         | 
| 4 | 
            +
              ss "reading Halo debugger ID - setting correct compare value"
         | 
| 5 | 
            +
              result = tester.transaction do 
         | 
| 6 | 
            +
                $dut.reg(:testreg).read(0x5ba00477)
         | 
| 7 | 
            +
                $dut.jtag.read_dr $dut.reg(:testreg), size: 32
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
              result_comment =  "transaction result: #{result}"
         | 
| 10 | 
            +
              ss result_comment
         | 
| 11 | 
            +
              
         | 
| 12 | 
            +
              ss "reading Halo debugger ID - setting wrong compare value"
         | 
| 13 | 
            +
              result = tester.transaction do
         | 
| 14 | 
            +
                $dut.reg(:testreg).read(0x5bd00477)
         | 
| 15 | 
            +
                $dut.jtag.read_dr $dut.reg(:testreg), size: 32
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
              result_comment = "transaction result: #{result}"
         | 
| 18 | 
            +
              ss result_comment
         | 
| 19 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: origen_link
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Paul Derouen
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016- | 
| 11 | 
            +
            date: 2016-05-11 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: origen
         | 
| @@ -95,6 +95,8 @@ files: | |
| 95 95 | 
             
            - config/version.rb
         | 
| 96 96 | 
             
            - lib/origen_link.rb
         | 
| 97 97 | 
             
            - lib/origen_link/callback_handlers.rb
         | 
| 98 | 
            +
            - lib/origen_link/capture_support.rb
         | 
| 99 | 
            +
            - lib/origen_link/configuration_commands.rb
         | 
| 98 100 | 
             
            - lib/origen_link/server/jtag.rb
         | 
| 99 101 | 
             
            - lib/origen_link/server/pin.rb
         | 
| 100 102 | 
             
            - lib/origen_link/server/sequencer.rb
         | 
| @@ -106,8 +108,10 @@ files: | |
| 106 108 | 
             
            - lib/tasks/origen_link.rake
         | 
| 107 109 | 
             
            - pattern/example.rb
         | 
| 108 110 | 
             
            - pattern/jtag_100_operations.rb
         | 
| 111 | 
            +
            - pattern/jtag_capture_id.rb
         | 
| 109 112 | 
             
            - pattern/jtag_comm_fail_test.rb
         | 
| 110 113 | 
             
            - pattern/jtag_comm_test.rb
         | 
| 114 | 
            +
            - pattern/transaction_test.rb
         | 
| 111 115 | 
             
            - templates/web/index.md.erb
         | 
| 112 116 | 
             
            - templates/web/layouts/_basic.html.erb
         | 
| 113 117 | 
             
            - templates/web/partials/_navbar.html.erb
         | 
| @@ -131,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 131 135 | 
             
                  version: 1.8.11
         | 
| 132 136 | 
             
            requirements: []
         | 
| 133 137 | 
             
            rubyforge_project: 
         | 
| 134 | 
            -
            rubygems_version: 2. | 
| 138 | 
            +
            rubygems_version: 2.2.2
         | 
| 135 139 | 
             
            signing_key: 
         | 
| 136 140 | 
             
            specification_version: 4
         | 
| 137 141 | 
             
            summary: Origen interface to a live DUT tester
         |