All Files (89.69% covered at 9.93 hits/line)
22 files in total.
708 relevant lines.
635 lines covered and
73 lines missed
-
1
require 'origen'
-
1
require_relative '../config/application.rb'
-
1
require 'origen_jtag'
-
1
require 'origen_swd'
-
-
1
module OrigenARMDebug
-
1
require 'origen_arm_debug/helpers'
-
1
require 'origen_arm_debug/dap'
-
1
require 'origen_arm_debug/dap_controller'
-
1
require 'origen_arm_debug/dp_controller'
-
1
require 'origen_arm_debug/dp_controller_v6'
-
1
require 'origen_arm_debug/jtag_dp'
-
1
require 'origen_arm_debug/jtag_dp_controller'
-
1
require 'origen_arm_debug/jtag_dp_v6'
-
1
require 'origen_arm_debug/jtag_dp_v6_controller'
-
1
require 'origen_arm_debug/sw_dp'
-
1
require 'origen_arm_debug/sw_dp_controller'
-
1
require 'origen_arm_debug/ap'
-
1
require 'origen_arm_debug/ap_controller'
-
1
require 'origen_arm_debug/mem_ap'
-
1
require 'origen_arm_debug/mem_ap_controller'
-
1
require 'origen_arm_debug/jtag_ap'
-
end
-
1
module OrigenARMDebug
-
# Generic Access Port (AP)
-
1
class AP
-
1
include Origen::Model
-
-
# Wait states for data to be transferred from AP-Reg to RDBUFF (on read)
-
1
attr_accessor :apreg_access_wait
-
-
1
def initialize(options = {})
-
24
@apreg_access_wait = options[:apreg_access_wait] || 0
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
1
class APController
-
1
include Origen::Controller
-
1
include Helpers
-
-
1
def write_register(reg_or_val, options = {})
-
if reg_or_val.try(:owner) == model
-
log "Write AP (#{model.name}) register #{reg_or_val.name.to_s.upcase}: #{reg_or_val.data.to_hex}" do
-
parent.dp.write_register(reg_or_val)
-
apreg_access_wait.cycles
-
end
-
else
-
fail 'No Resource-specific transport defined for MDM-AP (#model.name})'
-
end
-
end
-
-
1
def read_register(reg_or_val, options = {})
-
if reg_or_val.try(:owner) == model
-
log "Read AP (#{model.name}) register #{reg_or_val.name.to_s.upcase}: #{Origen::Utility.read_hex(reg_or_val)}" do
-
parent.dp.read_register(reg_or_val, apacc_wait_states: apreg_access_wait)
-
end
-
else
-
fail 'No Resource-specific transport defined for MDM-AP (#model.name})'
-
end
-
end
-
-
1
def base_address
-
model.base_address
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
# This is the top-level model that instantiates the DP and APs
-
1
class DAP
-
1
include Origen::Model
-
-
1
attr_reader :dps, :mem_aps, :jtag_aps, :ext_aps
-
-
1
def initialize(options = {})
-
12
@dps = []
-
12
@mem_aps = [] # Array of MEM-APs
-
12
@jtag_aps = [] # Array of JTAG-APs
-
12
@ext_aps = [] # Array of 'extension' APs
-
-
12
instantiate_subblocks(options)
-
end
-
-
1
def instantiate_subblocks(options = {})
-
12
if options[:swd] || parent.respond_to?(:swd)
-
3
dps << sub_block(:sw_dp, class_name: 'SW_DP')
-
end
-
-
12
if options[:jtag] || parent.respond_to?(:jtag)
-
10
if options[:dapv6]
-
3
options[:class_name] = 'JTAG_DPV6'
-
else
-
7
options[:class_name] = 'JTAG_DP'
-
end
-
10
dps << sub_block(:jtag_dp, options)
-
end
-
-
12
Array(options[:mem_aps]).each do |name, base_address|
-
24
if base_address.is_a?(Hash)
-
12
ap_opts = { class_name: 'MemAP' }.merge(base_address)
-
else
-
12
ap_opts = { class_name: 'MemAP', base_address: base_address }
-
end
-
-
24
add_ap(name, ap_opts)
-
end
-
-
12
Array(options[:jtag_aps]).each do |name, base_address|
-
if base_address.is_a?(Hash)
-
ap_opts = { class_name: 'JTAGAP' }.merge(base_address)
-
else
-
ap_opts = { class_name: 'JTAGAP', base_address: base_address }
-
end
-
-
add_ap(name, ap_opts)
-
end
-
-
12
Array(options[:aps]).each do |name, opts|
-
if opts.is_a?(Hash)
-
klass = opts.delete(:class_name)
-
addr = opts.delete(:base_address)
-
if klass.nil? || addr.nil?
-
fail "[ARM DEBUG] Error: Must specify class_name and base_address if using 'aps' hash to define APs"
-
end
-
ap_opts = { class_name: klass, base_address: addr }.merge(opts)
-
else
-
fail "[ARM DEBUG] Error: Must specify class_name and base_address if using 'aps' hash to define APs"
-
end
-
-
add_ap(name, ap_opts)
-
end
-
end
-
-
# Method to add additional Access Ports (MEM-AP)
-
#
-
# @param [Integer] name Short name for mem_ap that is being created
-
# @param [Hash] options Implemenation specific details
-
#
-
# @examples
-
# arm_debug.add_ap('alt_ahbapi', { class_name: 'OrigenARMDebug::MemAP', base_address: 0x02000000 })
-
#
-
1
def add_ap(name, options)
-
24
domain name.to_sym
-
# class name is deleted from options in sub_block call
-
24
class_name = options[:class_name]
-
24
ap = sub_block(name.to_sym, options)
-
-
24
if class_name == 'MemAP'
-
24
mem_aps << ap
-
elsif class_name == 'JTAGAP'
-
jtag_aps << ap
-
else
-
ext_aps << ap
-
end
-
end
-
-
# Returns an array containing all APs
-
1
def aps
-
mem_aps + jtag_aps + ext_aps
-
end
-
end
-
1
Driver = DAP # For legacy API compatibility
-
end
-
1
module OrigenARMDebug
-
1
class DAPController
-
1
include Origen::Controller
-
1
include Helpers
-
-
1
attr_accessor :dp
-
-
# Returns the currently enabled DP (or the only DP if only one
-
# of them).
-
# If no dp is enabled before calling this, it will choose the
-
# SW_DP by default.
-
1
def dp
-
95
@dp ||= dps.first
-
end
-
-
1
def set_dp(dp)
-
1
if dps.size > 1
-
1
if dp == :swd || dp == :sw
-
@dp = dps.first
-
1
elsif dp == :jtag
-
1
@dp = dps.last
-
else
-
Origen.log.error 'origen_arm_debug: Only SWD and JTAG DP available'
-
end
-
else
-
Origen.log.warn 'origen_arm_debug: Ignoring set_dp call since only one DP is available'
-
end
-
end
-
-
1
def reset_dp
-
1
@dp = nil
-
end
-
-
1
def is_jtag?
-
dp.is_jtag?
-
end
-
-
1
def is_swd?
-
dp.is_swd?
-
end
-
1
alias_method :is_sw?, :is_swd?
-
end
-
end
-
1
module OrigenARMDebug
-
# Common methods shared between the SW and JTAG DP controllers
-
1
module DPController
-
# Alias for the ctrlstat register
-
1
def ctrl_stat
-
ctrlstat
-
end
-
-
# @api private
-
1
def select_ap_reg(reg)
-
83
address = reg.address & 0xFFFF_FFF0
-
83
apsel = (reg.address & 0xFF00_0000) >> 24
-
83
apbanksel = (reg.address & 0xF0) >> 4
-
# if model.select.data != address
-
83
if model.select.apsel.data != apsel || model.select.apbanksel.data != apbanksel
-
5
model.select.write! do |r|
-
5
r.apsel.write apsel
-
5
r.apbanksel.write apbanksel
-
end
-
end
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
# Common methods shared between the SW and JTAG DP controllers
-
1
module DPControllerV6
-
# Alias for the ctrlstat register
-
1
def ctrl_stat
-
ctrlstat
-
end
-
-
# @api private
-
1
def select_ap_reg(reg)
-
2
address = (reg.address & 0xFFFF_FFF0) >> 4
-
2
address1 = (reg.address & 0xFFFF_FFFF_0000_0000) >> 32
-
2
model.select1.write! address1 if model.select1.data != address1
-
2
model.select.bits(:addr).write! address if model.select.bits(:addr).data != address
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
# Generic helper methods shared by the various controllers
-
1
module Helpers
-
1
def extract_data(reg_or_val, options = {})
-
21
if reg_or_val.respond_to?('data')
-
21
reg_or_val.data
-
else
-
reg_or_val
-
end
-
end
-
-
1
def extract_address(reg_or_val, options = {})
-
64
addr = options[:address] || options[:addr]
-
64
return addr if addr
-
64
return reg_or_val.address if reg_or_val.respond_to?('address')
-
return reg_or_val.addr if reg_or_val.respond_to?('addr')
-
fail 'No address given, if supplying a data value instead of a register object, you must supply an :address option'
-
end
-
-
1
def log(msg)
-
147
cc "[ARM Debug] #{msg}"
-
147
if block_given?
-
147
yield
-
147
cc "[ARM Debug] /#{msg}"
-
end
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
1
class JTAGAP < AP
-
1
def initialize(options = {})
-
super
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
1
class JTAG_DP
-
1
include Origen::Model
-
-
1
attr_reader :dpacc_select, :apacc_select
-
-
1
def initialize(options = {})
-
options = {
-
7
ir_size: 4,
-
idcode_select: 0b1110,
-
abort_select: 0b1000,
-
dpacc_select: 0b1010,
-
apacc_select: 0b1011
-
}.merge(options)
-
7
@dpacc_select = options[:dpacc_select]
-
7
@apacc_select = options[:apacc_select]
-
7
add_reg :ir, 0, size: options[:ir_size]
-
-
# Virtual reg used to represent all of the various 35-bit scan chains
-
7
reg :dr, 0, size: 35 do |reg|
-
7
reg.bit 34..3, :data
-
7
reg.bit 2..1, :a
-
7
reg.bit 0, :rnw
-
end
-
-
7
reg :idcode, options[:idcode_select], access: :ro do |reg|
-
7
reg.bit 31..28, :version
-
7
reg.bit 27..12, :partno
-
7
reg.bit 11..1, :designer
-
7
reg.bit 0, :bit0, reset: 1
-
end
-
-
7
reg :ctrlstat, 0x4 do |reg|
-
7
reg.bit 31, :csyspwrupack
-
7
reg.bit 30, :csyspwrupreq
-
7
reg.bit 29, :cdbgpwrupack
-
7
reg.bit 28, :cdbgpwrupreq
-
7
reg.bit 27, :cdbgrstack
-
7
reg.bit 26, :cdbgrstreq
-
7
reg.bit 23..12, :trncnt
-
7
reg.bit 11..8, :masklane
-
7
reg.bit 5, :stickyerr
-
7
reg.bit 4, :stickycmp
-
7
reg.bit 3..2, :trnmode
-
7
reg.bit 1, :stickyorun
-
7
reg.bit 0, :orundetect
-
end
-
-
7
reg :select, 0x8 do |reg|
-
7
reg.bit 31..24, :apsel
-
7
reg.bit 23..8, :reserved
-
7
reg.bit 7..4, :apbanksel
-
end
-
-
7
select.write options[:dp_select_reset] if options[:dp_select_reset]
-
-
7
add_reg :rdbuff, 0xC, access: :ro, reset: 0
-
-
7
reg :abort, options[:abort_select], access: :wo do |reg|
-
7
reg.bit 0, :dapabort
-
end
-
end
-
-
1
def select
-
126
reg(:select)
-
end
-
-
1
def abort
-
3
reg(:abort)
-
end
-
-
1
def is_jtag?
-
true
-
end
-
-
1
def is_swd?
-
false
-
end
-
1
alias_method :is_sw?, :is_swd?
-
end
-
end
-
1
module OrigenARMDebug
-
1
class JTAG_DPController
-
1
include Origen::Controller
-
1
include Helpers
-
1
include DPController
-
-
1
def write_register(reg, options = {})
-
144
unless reg.writable?
-
fail "The :#{reg.name} register is not writeable!"
-
end
-
-
# DP register write
-
144
if reg.owner == model
-
# Don't log this one, not really a DP reg and will be included
-
# in the JTAG driver log anyway
-
120
if reg.name == :ir
-
108
dut.jtag.write_ir(reg)
-
else
-
-
12
log "Write JTAG-DP register #{reg.name.to_s.upcase}: #{reg.data.to_hex}" do
-
12
if reg.name == :abort
-
3
ir.write!(reg.offset)
-
3
dr.reset
-
3
dr.overlay(nil)
-
3
dr[2..0].write(0)
-
3
dr[34..3].copy_all(reg)
-
3
dut.jtag.write_dr(dr)
-
-
# DPACC
-
9
elsif reg.name == :ctrlstat || reg.name == :select
-
9
dr.reset
-
9
dr.overlay(nil)
-
9
dr[0].write(0)
-
9
dr[2..1].write(reg.offset >> 2)
-
9
dr[34..3].copy_all(reg)
-
9
ir.write!(dpacc_select)
-
9
dut.jtag.write_dr(dr)
-
-
else
-
fail "Can't write #{reg.name}"
-
end
-
end
-
end
-
-
# AP register write
-
else
-
-
24
unless reg.owner.is_a?(AP)
-
fail 'The JTAG-DP can only write to DP or AP registers!'
-
end
-
-
24
select_ap_reg(reg)
-
24
dr.reset
-
24
dr.overlay(nil)
-
24
dr[0].write(0)
-
24
dr[2..1].write(reg.offset >> 2)
-
24
dr[34..3].copy_all(reg)
-
24
ir.write!(apacc_select)
-
24
dut.jtag.write_dr(dr, options)
-
end
-
end
-
-
1
def read_register(reg, options = {})
-
39
unless reg.readable?
-
fail "The :#{reg.name} register is not readable!"
-
end
-
-
39
if reg.owner == model
-
# Don't log this one, not really a DP reg and will be included
-
# in the JTAG driver log anyway
-
6
if reg.name == :ir
-
dut.jtag.read_ir(reg)
-
else
-
-
6
log "Read JTAG-DP register #{reg.name.to_s.upcase}: #{Origen::Utility.read_hex(reg)}" do
-
6
if reg.name == :idcode
-
3
ir.write!(reg.offset)
-
3
dut.jtag.read_dr(reg)
-
-
# DPACC
-
3
elsif reg.name == :ctrlstat || reg.name == :select || reg.name == :rdbuff
-
-
# Part 1 - Request read from DP-Register by writing to DPACC with RnW=1
-
3
dr.reset
-
3
dr.overlay(nil)
-
3
dr[0].write(1)
-
3
dr[2..1].write(reg.offset >> 2)
-
3
dr[34..3].write(0)
-
3
ir.write!(dpacc_select)
-
3
dut.jtag.write_dr(dr)
-
-
# Part 2 - Now read real data from RDBUFF (DP-Reg)
-
3
dr.reset
-
3
dr.overlay(nil)
-
3
dr[0].write(1)
-
3
dr[2..1].write(rdbuff.offset >> 2)
-
3
dr[34..3].copy_all(reg)
-
3
options[:mask] = options[:mask] << 3 unless options[:mask].nil?
-
3
dut.jtag.read_dr(dr, options)
-
-
else
-
fail "Can't read #{reg.name}"
-
end
-
end
-
end
-
-
# AP register read
-
else
-
33
unless reg.owner.is_a?(AP)
-
fail 'The JTAG-DP can only write to DP or AP registers!'
-
end
-
-
# Part 1 - Request read from AP-Register by writing to APACC with RnW=1
-
33
select_ap_reg(reg)
-
33
dr.reset
-
33
dr.overlay(nil)
-
33
dr[0].write(1)
-
33
dr[2..1].write(reg.offset >> 2)
-
33
dr[34..3].write(0)
-
33
ir.write!(apacc_select)
-
33
dut.jtag.write_dr(dr)
-
-
# Calling AP should provide any delay parameter for wait states between AP read request
-
# and when the data is available at the RDBUFF DP-Reg
-
33
if options[:apacc_wait_states]
-
33
options[:apacc_wait_states].cycles
-
end
-
-
# Part 2 - Now read real data from RDBUFF (DP-Reg)
-
33
dr.reset
-
33
dr.overlay(nil)
-
33
dr[0].write(1)
-
33
dr[2..1].write(rdbuff.offset >> 2)
-
33
dr[34..3].copy_all(reg)
-
33
options[:mask] = options[:mask] << 3 unless options[:mask].nil?
-
33
ir.write!(dpacc_select)
-
33
dut.jtag.read_dr(dr, options)
-
end
-
end
-
-
1
def base_address
-
model.base_address
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
1
class JTAG_DPV6
-
1
include Origen::Model
-
-
1
attr_reader :dpacc_select, :apacc_select
-
-
1
def initialize(options = {})
-
options = {
-
3
ir_size: 4,
-
idcode_select: 0b1110,
-
abort_select: 0b1000,
-
dpacc_select: 0b1010,
-
apacc_select: 0b1011
-
}.merge(options)
-
3
@dpacc_select = options[:dpacc_select]
-
3
@apacc_select = options[:apacc_select]
-
3
add_reg :ir, 0, size: options[:ir_size]
-
-
# Virtual reg used to represent all of the various 35-bit scan chains
-
3
reg :dr, 0, size: 35 do |reg|
-
3
reg.bit 34..3, :data
-
3
reg.bit 2..1, :a
-
3
reg.bit 0, :rnw
-
end
-
-
3
reg :idcode, options[:idcode_select], access: :ro do |reg|
-
3
reg.bit 31..28, :version
-
3
reg.bit 27..12, :partno
-
3
reg.bit 11..1, :designer
-
3
reg.bit 0, :bit0, reset: 1
-
end
-
-
3
reg :ctrlstat, 0x4, dpbanksel: 0 do |reg|
-
3
reg.bit 31, :csyspwrupack
-
3
reg.bit 30, :csyspwrupreq
-
3
reg.bit 29, :cdbgpwrupack
-
3
reg.bit 28, :cdbgpwrupreq
-
3
reg.bit 27, :cdbgrstack
-
3
reg.bit 26, :cdbgrstreq
-
3
reg.bit 23..12, :trncnt
-
3
reg.bit 11..8, :masklane
-
3
reg.bit 7, :wdataerr
-
3
reg.bit 6, :readok
-
3
reg.bit 5, :stickyerr
-
3
reg.bit 4, :stickycmp
-
3
reg.bit 3..2, :trnmode
-
3
reg.bit 1, :stickyorun
-
3
reg.bit 0, :orundetect
-
end
-
-
3
reg :select, 0x8 do |reg|
-
3
reg.bit 31..4, :addr
-
3
reg.bit 3..0, :dpbanksel
-
end
-
-
3
reg :select1, 0x4, dpbanksel: 5 do |reg|
-
3
reg.bit 31..0, :addr
-
end
-
-
3
select.write options[:dp_select_reset] if options[:dp_select_reset]
-
-
3
add_reg :rdbuff, 0xC, access: :ro, reset: 0
-
-
3
reg :abort, options[:abort_select], access: :wo do |reg|
-
3
reg.bit 0, :dapabort
-
end
-
end
-
-
1
def select
-
8
reg(:select)
-
end
-
-
1
def abort
-
1
reg(:abort)
-
end
-
-
1
def is_jtag?
-
true
-
end
-
-
1
def is_swd?
-
false
-
end
-
1
alias_method :is_sw?, :is_swd?
-
end
-
end
-
1
module OrigenARMDebug
-
1
class JTAG_DPV6Controller
-
1
include Origen::Controller
-
1
include Helpers
-
1
include DPControllerV6
-
-
1
def write_register(reg, options = {})
-
22
unless reg.writable?
-
fail "The :#{reg.name} register is not writeable!"
-
end
-
-
# DP register write
-
22
if reg.owner == model
-
# Don't log this one, not really a DP reg and will be included
-
# in the JTAG driver log anyway
-
21
if reg.name == :ir
-
14
dut.jtag.write_ir(reg)
-
else
-
-
7
log "Write JTAG-DP register #{reg.name.to_s.upcase}: #{reg.data.to_hex}" do
-
7
if reg.name == :abort
-
1
ir.write!(reg.offset)
-
1
dr.reset
-
1
dr.overlay(nil)
-
1
dr[2..0].write(0)
-
1
dr[34..3].copy_all(reg)
-
1
dut.jtag.write_dr(dr)
-
-
# DPACC
-
6
elsif reg.name == :select
-
3
dp_write(reg)
-
-
# Some other debug register
-
3
elsif reg.meta.include?(:dpbanksel)
-
3
if model.reg(:select).bits(:dpbanksel).data != reg.meta[:dpbanksel]
-
1
model.reg(:select).bits(:dpbanksel).write! reg.meta[:dpbanksel]
-
end
-
3
dp_write(reg)
-
-
else
-
fail "Can't write #{reg.name}"
-
end
-
end
-
end
-
-
# AP register write
-
else
-
-
1
unless reg.owner.is_a?(AP)
-
fail 'The JTAG-DP can only write to DP or AP registers!'
-
end
-
-
1
select_ap_reg(reg)
-
1
dr.reset
-
1
dr.overlay(nil)
-
1
dr[0].write(0)
-
1
dr[2..1].write(reg.offset >> 2)
-
1
dr[34..3].copy_all(reg)
-
1
ir.write!(apacc_select)
-
1
dut.jtag.write_dr(dr, options)
-
end
-
end
-
-
1
def read_register(reg, options = {})
-
5
unless reg.readable?
-
fail "The :#{reg.name} register is not readable!"
-
end
-
-
5
if reg.owner == model
-
# Don't log this one, not really a DP reg and will be included
-
# in the JTAG driver log anyway
-
4
if reg.name == :ir
-
dut.jtag.read_ir(reg)
-
else
-
-
4
log "Read JTAG-DP register #{reg.name.to_s.upcase}: #{Origen::Utility.read_hex(reg)}" do
-
4
if reg.name == :idcode
-
1
ir.write!(reg.offset)
-
1
dut.jtag.read_dr(reg)
-
-
# DPACC
-
3
elsif reg.name == :select || reg.name == :rdbuff
-
1
dp_read(reg, options)
-
-
# Some other register
-
2
elsif reg.meta.include?(:dpbanksel)
-
# Part 1 - Set dpbanksel if required
-
2
if model.reg(:select).bits(:dpbanksel).data != reg.meta[:dpbanksel]
-
model.reg(:select).bits(:dpbanksel).write! reg.meta[:dpbanksel]
-
end
-
-
2
dp_read(reg, options)
-
-
else
-
fail "Can't read #{reg.name}"
-
end
-
end
-
end
-
-
# AP register read
-
else
-
1
unless reg.owner.is_a?(AP)
-
fail 'The JTAG-DP can only write to DP or AP registers!'
-
end
-
-
# Part 1 - Request read from AP-Register by writing to APACC with RnW=1
-
1
select_ap_reg(reg)
-
1
dr.reset
-
1
dr.overlay(nil)
-
1
dr[0].write(1)
-
1
dr[2..1].write(reg.offset >> 2)
-
1
dr[34..3].write(0)
-
1
ir.write!(apacc_select)
-
1
dut.jtag.write_dr(dr)
-
-
# Calling AP should provide any delay parameter for wait states between AP read request
-
# and when the data is available at the RDBUFF DP-Reg
-
1
if options[:apacc_wait_states]
-
1
options[:apacc_wait_states].cycles
-
end
-
-
# Part 2 - Now read real data from RDBUFF (DP-Reg)
-
1
dr.reset
-
1
dr.overlay(nil)
-
1
dr[0].write(1)
-
1
dr[2..1].write(rdbuff.offset >> 2)
-
1
dr[34..3].copy_all(reg)
-
1
options[:mask] = options[:mask] << 3 unless options[:mask].nil?
-
1
ir.write!(dpacc_select)
-
1
dut.jtag.read_dr(dr, options)
-
end
-
end
-
-
1
def dp_read(reg, options = {})
-
# Part 1 - Request read from DP-Register by writing to DPACC with RnW=1
-
3
dr.reset
-
3
dr.overlay(nil)
-
3
dr[0].write(1)
-
3
dr[2..1].write(reg.offset >> 2)
-
3
dr[34..3].write(0)
-
3
ir.write!(dpacc_select)
-
3
dut.jtag.write_dr(dr)
-
-
# Part 2 - Now read real data from RDBUFF (DP-Reg)
-
3
dr.reset
-
3
dr.overlay(nil)
-
3
dr[0].write(1)
-
3
dr[2..1].write(rdbuff.offset >> 2)
-
3
dr[34..3].copy_all(reg)
-
3
options[:mask] = options[:mask] << 3 unless options[:mask].nil?
-
3
dut.jtag.read_dr(dr, options)
-
end
-
-
1
def dp_write(reg)
-
6
dr.reset
-
6
dr.overlay(nil)
-
6
dr[0].write(0)
-
6
dr[2..1].write(reg.offset >> 2)
-
6
dr[34..3].copy_all(reg)
-
6
ir.write!(dpacc_select)
-
6
dut.jtag.write_dr(dr)
-
end
-
-
1
def base_address
-
model.base_address
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
# Memory Access Port (MEM-AP)
-
1
class MemAP < AP
-
# Latency to write a memory resource
-
1
attr_accessor :latency
-
-
# Wait states for data to be transferred from Memory Resource to DRW on
-
# read request. Should be added to apreg_access_wait for complete transaction
-
# time of memory read (read data path: memory->drw->rdbuff)
-
1
attr_accessor :apmem_access_wait
-
-
# Wait states to occur in between configuring the DAP for a read, and for the the read transaction to begin.
-
# For JTAG, this is the wait states in between setting the AP and for the read transaction to occur.
-
# For SWD, this is the wait states in between setting the AP, initiating and completing a dummy read, and beginning the actual read transaction.
-
1
attr_accessor :apacc_wait_states
-
-
# Boolean value indicating whether this is an AXI-AP
-
1
attr_accessor :is_axi
-
-
# Value to be read from DP CSW for interleaved status checks (debug feature)
-
1
attr_accessor :csw_status_check
-
-
# Boolean value indicating whether to interleave status checks during transactions (debug feature)
-
1
attr_accessor :interleave_status_check
-
-
1
def initialize(options = {})
-
24
super
-
-
24
@is_axi = options[:is_axi]
-
24
@csw_status_check = options[:csw_status_check]
-
24
@interleave_status_check = options[:interleave_status_check]
-
-
24
@latency = options[:latency] || 0
-
24
@apmem_access_wait = options[:apmem_access_wait] || 0
-
-
24
if @is_axi
-
6
reg :csw, 0x0 do |reg|
-
6
reg.bit 31, :reserved
-
6
reg.bit 30..28, :prot, res: 3
-
6
reg.bit 27..24, :cache
-
6
reg.bit 23, :spiden
-
6
reg.bit 22..15, :reserved2
-
6
reg.bit 14..13, :domain, res: 3
-
6
reg.bit 12, :ace_enable
-
6
reg.bit 11..8, :mode
-
6
reg.bit 7, :tr_in_prog
-
6
reg.bit 6, :dbg_status, res: 1
-
6
reg.bit 5..4, :addr_inc
-
6
reg.bit 3, :reserved3
-
6
reg.bit 2..0, :size, res: 2
-
end
-
else
-
18
reg :csw, 0x0 do |reg|
-
18
reg.bit 31, :dbg_sw_enable
-
18
reg.bit 30..24, :prot
-
18
reg.bit 23, :spiden
-
18
reg.bit 11..8, :mode
-
18
reg.bit 7, :tr_in_prog
-
18
reg.bit 6, :device_en
-
18
reg.bit 5..4, :addr_inc
-
18
reg.bit 2..0, :size
-
end
-
end
-
24
reg(:csw).write(options[:csw_reset]) if options[:csw_reset]
-
-
# Doesn't really reset to all 1's, but just to make sure the address
-
# optimization logic does not kick in on the first transaction
-
24
add_reg :tar, 0x04, reset: 0xFFFFFFFF
-
24
add_reg :drw, 0x0C, reset: :undefined
-
24
add_reg :bd0, 0x10, reset: :undefined
-
24
add_reg :bd1, 0x14, reset: :undefined
-
24
add_reg :bd2, 0x18, reset: :undefined
-
24
add_reg :bd3, 0x1C, reset: :undefined
-
-
24
reg :cfg, 0xF4, access: :ro do |reg|
-
24
reg.bit 0, :big_endian
-
end
-
-
24
reg :base, 0xF8, access: :ro do |reg|
-
24
reg.bit 31..12, :baseaddr
-
24
reg.bit 1, :format, reset: 1
-
24
reg.bit 0, :entry_present
-
end
-
-
24
add_reg :idr, 0xFC, access: :ro
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
1
class MemAPController < APController
-
1
def write_register(reg_or_val, options = {})
-
57
if reg_or_val.try(:owner) == model
-
36
log "Write MEM-AP (#{model.name}) register #{reg_or_val.name.to_s.upcase}: #{reg_or_val.data.to_hex}" do
-
36
parent.dp.write_register(reg_or_val, options)
-
36
apreg_access_wait.cycles
-
end
-
else
-
-
21
addr = extract_address(reg_or_val, options)
-
21
data = extract_data(reg_or_val, options)
-
21
ovl = options.delete(:overlay)
-
21
unless ovl.nil?
-
Origen.log.warn '[ARM Debug] Overlays only supported through register model'
-
end
-
-
21
log "Write MEM-AP (#{model.name}) address #{addr.to_hex}: #{data.to_hex}" do
-
21
csw.bits(:size).write!(0b010) if csw.bits(:size).data != 0b010
-
21
tar.write!(addr) unless tar.data == addr
-
21
parent.dp.ctrlstat.read! model.csw_status_check if model.interleave_status_check
-
21
drw.reset
-
21
drw.overlay(nil)
-
21
drw.copy_all(reg_or_val)
-
21
drw.write!(options)
-
21
latency.cycles
-
21
parent.dp.ctrlstat.read! model.csw_status_check if model.interleave_status_check
-
end
-
21
increment_addr
-
end
-
end
-
-
1
def read_register(reg_or_val, options = {})
-
49
if reg_or_val.try(:owner) == model
-
6
apacc_wait_states = reg_or_val.name == :drw ? (apmem_access_wait + apreg_access_wait) : apreg_access_wait
-
6
log "Read MEM-AP (#{model.name}) register #{reg_or_val.name.to_s.upcase}: #{Origen::Utility.read_hex(reg_or_val)}" do
-
6
parent.dp.read_register(reg_or_val, options.merge(apacc_wait_states: apacc_wait_states))
-
end
-
-
else
-
-
43
addr = extract_address(reg_or_val, options)
-
-
43
log "Read MEM-AP (#{model.name}) address #{addr.to_hex}: #{Origen::Utility.read_hex(reg_or_val)}" do
-
43
csw.bits(:size).write!(0b010) if csw.bits(:size).data != 0b010
-
43
unless tar.data == addr
-
tar.write!(addr)
-
parent.dp.ctrlstat.read! model.csw_status_check if model.interleave_status_check
-
end
-
43
drw.reset
-
43
drw.overlay(nil)
-
43
drw.copy_all(reg_or_val)
-
43
parent.dp.read_register(drw, options.merge(apacc_wait_states: (apmem_access_wait + apreg_access_wait)))
-
43
parent.dp.ctrlstat.read! model.csw_status_check if model.interleave_status_check
-
end
-
43
increment_addr
-
end
-
-
49
reg_or_val.clear_flags if reg_or_val.respond_to?(:clear_flags)
-
end
-
-
1
def address_increment_enabled?
-
128
d = csw.addr_inc.data
-
128
d == 1 || d == 2
-
end
-
-
1
private
-
-
# Update the model if the address is auto-incrementing on chip
-
1
def increment_addr
-
64
if address_increment_enabled?
-
case csw.bits(:size).data
-
when 0 then tar.data += 1 # Increment single
-
when 1 then tar.data += 2 # Increment single
-
when 2 then tar.data += 4 # Increment single
-
end
-
64
elsif csw.addr_inc.data == 2
-
tar.data += 4 # Increment packed
-
end
-
-
# Reset tar if just crossed a 1kB boundary
-
64
if address_increment_enabled? && (tar[9..0].data == 0)
-
tar.write(0)
-
end
-
end
-
end
-
end
-
1
module OrigenARMDebug
-
1
class SW_DP
-
1
include Origen::Model
-
-
1
def initialize(options = {})
-
3
reg :idcode, 0, access: :ro do |reg|
-
3
reg.bit 31..28, :version
-
3
reg.bit 27..12, :partno
-
3
reg.bit 11..1, :designer
-
3
reg.bit 0, :bit0, reset: 1
-
end
-
-
3
reg :abort, 0, access: :wo do |reg|
-
3
reg.bit 4, :orunerrclr
-
3
reg.bit 3, :wderrclr
-
3
reg.bit 2, :stkerrclr
-
3
reg.bit 1, :stkcmpclr
-
3
reg.bit 0, :dapabort
-
end
-
-
3
reg :ctrlstat, 0x4 do |reg|
-
3
reg.bit 31, :csyspwrupack
-
3
reg.bit 30, :csyspwrupreq
-
3
reg.bit 29, :cdbgpwrupack
-
3
reg.bit 28, :cdbgpwrupreq
-
3
reg.bit 27, :cdbgrstack
-
3
reg.bit 26, :cdbgrstreq
-
3
reg.bit 23..12, :trncnt
-
3
reg.bit 11..8, :masklane
-
3
reg.bit 7, :wdataerr
-
3
reg.bit 6, :readok
-
3
reg.bit 5, :stickyerr
-
3
reg.bit 4, :stickycmp
-
3
reg.bit 3..2, :trnmode
-
3
reg.bit 1, :stickyorun
-
3
reg.bit 0, :orundetect
-
end
-
-
3
reg :wcr, 0x4 do |reg|
-
3
reg.bit 9..8, :turnround
-
3
reg.bit 7..6, :wiremode
-
3
reg.bit 2..0, :prescaler
-
end
-
-
3
add_reg :resend, 0x8, access: :ro
-
-
3
reg :select, 0x8, access: :wo do |reg|
-
3
reg.bit 31..24, :apsel
-
3
reg.bit 7..4, :apbanksel
-
3
reg.bit 0, :ctrlsel
-
end
-
-
3
add_reg :rdbuff, 0xC, access: :ro
-
end
-
-
1
def select
-
58
reg(:select)
-
end
-
-
1
def abort
-
2
reg(:abort)
-
end
-
-
1
def is_jtag?
-
false
-
end
-
-
1
def is_swd?
-
true
-
end
-
1
alias_method :is_sw?, :is_swd?
-
end
-
end
-
1
module OrigenARMDebug
-
1
class SW_DPController
-
1
include Origen::Controller
-
1
include Helpers
-
1
include DPController
-
-
1
def write_register(reg, options = {})
-
19
unless reg.writable?
-
fail "The :#{reg.name} register is not writeable!"
-
end
-
-
19
if reg.owner == model
-
8
log "Write SW-DP register #{reg.name.to_s.upcase}: #{reg.data.to_hex}" do
-
8
dut.swd.write_dp(reg)
-
end
-
else
-
11
unless reg.owner.is_a?(AP)
-
fail 'The SW-DP can only write to DP or AP registers!'
-
end
-
-
11
select_ap_reg(reg)
-
11
dut.swd.write_ap(reg, options)
-
end
-
end
-
-
1
def read_register(reg, options = {})
-
19
unless reg.readable?
-
fail "The :#{reg.name} register is not readable!"
-
end
-
-
19
if reg.owner == model
-
4
log "Read SW-DP register #{reg.name.to_s.upcase}: #{Origen::Utility.read_hex(reg)}" do
-
4
dut.swd.read_dp(reg)
-
end
-
else
-
15
unless reg.owner.is_a?(AP)
-
fail 'The SW-DP can only write to DP or AP registers!'
-
end
-
-
15
select_ap_reg(reg)
-
15
dut.swd.read_ap(address: reg.address)
-
-
# Add any extra delay needed in between selecting the AP state, initiating and completing a dummy read, and
-
# starting the actual read.
-
15
if options[:apacc_wait_states]
-
15
options[:apacc_wait_states].cycles
-
end
-
-
15
dut.swd.read_dp(reg, options.merge(address: rdbuff.address))
-
end
-
end
-
end
-
end
-
1
module OrigenARMDebugDev
-
# This is a dummy DUT model which is used
-
# to instantiate and test the ARMDebug locally
-
# during development.
-
#
-
# It is not included when this library is imported.
-
1
class DUT
-
1
include Origen::TopLevel
-
1
include OrigenARMDebug
-
-
# Initializes simple dut model with test register and required jtag/swd pins
-
#
-
# @example
-
# $dut = OrigenARMDebugDev::DUT.new
-
#
-
1
def initialize(options = {})
-
9
add_reg :test, 0
-
-
9
reg :test2, 0 do |reg|
-
9
reg.bit 31, :msb
-
9
reg.bit 30..1, :data
-
9
reg.bit 0, :lsb
-
end
-
end
-
-
# Add any custom startup business here.
-
#
-
# @param [Hash] options Options to customize the operation
-
1
def startup(options)
-
6
tester.set_timeset('arm_debug', 40)
-
end
-
-
# Read data from a register
-
#
-
# @param [Register] reg Register name or address value
-
# @param [Hash] options Options to customize the operation
-
1
def read_register(reg, options = {})
-
43
arm_debug.mem_ap.read_register(reg, options)
-
end
-
-
# Write data to a register
-
#
-
# @param [Register] reg Register name or address value
-
# @param [Hash] options Options to customize the operation
-
1
def write_register(reg, options = {})
-
21
arm_debug.mem_ap.write_register(reg, options)
-
end
-
end
-
end
-
1
module OrigenARMDebugDev
-
# Simple JTAG-specific dut model that inherits from protocol-agnostic DUT model
-
1
class DUAL_DP_DUT < DUT
-
1
include OrigenSWD
-
1
include OrigenJTAG
-
-
# Adds jtag-required pins to the simple dut model
-
# Returns nothing.
-
1
def initialize(options = {})
-
1
super
-
1
add_pin :tclk
-
1
add_pin :tdi
-
1
add_pin :tdo
-
1
add_pin :tms
-
1
add_pin :trst
-
1
add_pin :swd_clk
-
1
add_pin :swd_dio
-
-
1
options[:class_name] = 'OrigenARMDebug::DAP'
-
1
options[:mem_aps] = {
-
mem_ap: {
-
base_address: 0x00000000,
-
latency: 16,
-
apreg_access_wait: 8,
-
apmem_access_wait: 8,
-
csw_reset: 0x23000040
-
},
-
mdm_ap: 0x01000000
-
}
-
# Specify (customize) ARM Debug implementation details
-
1
sub_block :arm_debug, options
-
end
-
end
-
end
-
1
module OrigenARMDebugDev
-
# Simple JTAG-specific dut model that inherits from protocol-agnostic DUT model
-
1
class JTAG_DUT < DUT
-
1
include OrigenJTAG
-
-
# Adds jtag-required pins to the simple dut model
-
# Returns nothing.
-
1
def initialize(options = {})
-
3
super
-
3
add_pin :tclk
-
3
add_pin :tdi
-
3
add_pin :tdo
-
3
add_pin :tms
-
3
add_pin :trst
-
3
add_pin :swd_clk
-
3
add_pin :swd_dio
-
-
3
options[:class_name] = 'OrigenARMDebug::DAP'
-
3
options[:mem_aps] = {
-
mem_ap: {
-
base_address: 0x00000000,
-
latency: 16,
-
apreg_access_wait: 8,
-
apmem_access_wait: 8,
-
csw_reset: 0x23000040
-
},
-
mdm_ap: 0x01000000
-
}
-
# Specify (customize) ARM Debug implementation details
-
3
sub_block :arm_debug, options
-
end
-
end
-
end
-
1
module OrigenARMDebugDev
-
# Simple JTAG-specific dut model that inherits from protocol-agnostic DUT model
-
1
class JTAG_AXI_DUT < DUT
-
1
include OrigenJTAG
-
-
# Adds jtag-required pins to the simple dut model
-
# Returns nothing.
-
1
def initialize(options = {})
-
3
super
-
3
add_pin :tclk
-
3
add_pin :tdi
-
3
add_pin :tdo
-
3
add_pin :tms
-
3
add_pin :trst
-
3
add_pin :swd_clk
-
3
add_pin :swd_dio
-
-
3
options[:class_name] = 'OrigenARMDebug::DAP'
-
3
options[:mem_aps] = {
-
mem_ap: {
-
base_address: 0x00000000,
-
latency: 16,
-
apreg_access_wait: 8,
-
apmem_access_wait: 8,
-
is_axi: true,
-
csw_reset: 0x1080_6002
-
},
-
mdm_ap: 0x01000000
-
}
-
3
options[:dp_select_reset] = 0xC2_0D00
-
# Specify (customize) ARM Debug implementation details
-
3
sub_block :arm_debug, options
-
-
3
options[:dapv6] = true
-
3
options[:class_name] = 'OrigenARMDebug::DAP'
-
3
options[:mem_aps] = {
-
mem_ap: {
-
base_address: 0x00C2_0000,
-
latency: 16,
-
apreg_access_wait: 8,
-
apmem_access_wait: 8,
-
is_axi: true,
-
csw_reset: 0x1080_6002
-
},
-
mdm_ap: 0x00C3_0000
-
}
-
3
sub_block :arm_debugv6, options
-
end
-
end
-
end
-
1
module OrigenARMDebugDev
-
# Simple SWD-specific dut model that inherits from protocol-agnostic DUT model
-
1
class SWD_DUT < DUT
-
1
include OrigenSWD
-
-
# Adds swd-required pins to the simple dut model
-
# Returns nothing.
-
1
def initialize
-
2
super
-
2
add_pin :tclk
-
2
add_pin :tdi
-
2
add_pin :tdo
-
2
add_pin :tms
-
2
add_pin :trst
-
2
add_pin :swd_clk
-
2
add_pin :swd_dio
-
-
2
sub_block :arm_debug, class_name: 'OrigenARMDebug::DAP',
-
mem_aps: {
-
mem_ap: { base_address: 0x00000000, csw_reset: 0x23000042 },
-
mdm_ap: 0x01000000
-
}
-
end
-
end
-
end