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