Class: OrigenARM::Cores::CortexM::BaseController

Inherits:
BaseController show all
Includes:
Origen::Controller
Defined in:
lib/origen_arm/cores/cortexm/base_cortexm/cortexm_controller.rb

Direct Known Subclasses

CM33Controller

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ BaseController

Returns a new instance of BaseController



7
8
9
# File 'lib/origen_arm/cores/cortexm/base_cortexm/cortexm_controller.rb', line 7

def initialize(options={})
  super
end

Instance Method Details

#core_reg_to_dcrdr(reg, options) ⇒ Object

TODO:

Implement Raise condition.

Note:

This is a shortcut to a reg.read! call that masks all the bits.

Note:

See the implementation of #write_register for additional details on the internals.

Note:

All core registers are 32-bits. Any contents in the DCRDR will be overwritten.

Reads the core register and places its contents in the DCRDR, but does not invoke and tester-level compares.

Raises:

  • (OrigenARM::CoreRegisterError)

    If reg is not a core register.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/origen_arm/cores/cortexm/base_cortexm/cortexm_controller.rb', line 120

def core_reg_to_dcrdr(reg, options)
  if reg_wrapped_by_dcrsr?(reg)
    pp("Copying Core Register to DCRDR: DCRDR <- #{reg.name}.data") do
      reg(:dcrsr).bits(:regwnr).write(0)
      reg(:dcrsr).bits(:reg_sel).write(reg.address)
      reg(:dcrsr).write!
      tester.cycle(repeat: read_debug_register_delay)
    end
  else
    Origen.app.fail!(
      message: "Method #core_reg_to_dcrdr can only be run with the core debug registers. " + \
               "Given register #{reg.is_a?(Register) ? reg.name : reg.to_s} is not classified as a core register.",
      exception: OrigenARM::CoreRegisterError
    )
  end
end

#enter_debug_mode_delay!Object

Note:

The delay (in cycles) can be set by initializing the core subblock parameter :enter_debug_mode_delay_cycles.

Note:

If the DUT provides the same method, that method will be used in place of this one.

Delays for the core to to enter debug mode.



16
17
18
19
20
21
22
23
24
# File 'lib/origen_arm/cores/cortexm/base_cortexm/cortexm_controller.rb', line 16

def enter_debug_mode_delay!
  if dut.respond_to?('enter_debug_mode_delay!'.to_sym)
    cc 'Using DUT-defined #enter_debug_mode_delay! for core to enter debug mode'
    dut.enter_debug_mode_delay!
  else
    cc "Delaying #{enter_debug_mode_delay_cycles} cycles for core to enter debug mode"
    tester.cycle(repeat: enter_debug_mode_delay_cycles)
  end
end

#exit_debug_mode_delay!Object

Note:

The delay (in cycles) can be set by initializing the core subblock parameter :exit_debug_mode_delay_cycles.

Note:

If the DUT provides the same method, that method will be used in place of this one.

Delays for the core to to exit debug mode.



31
32
33
34
35
36
37
38
39
# File 'lib/origen_arm/cores/cortexm/base_cortexm/cortexm_controller.rb', line 31

def exit_debug_mode_delay!
  if dut.respond_to?('exit_debug_mode_delay!'.to_sym)
    cc 'Using DUT-defined #exit_debug_mode_delay! for core to exit debug mode'
    dut.exit_debug_mode_delay!
  else
    cc "Delaying #{exit_debug_mode_delay_cycles} cycles for core to exit debug mode"
    tester.cycle(repeat: exit_debug_mode_delay_cycles)
  end
end

#in_debug_mode(with_core_halted: false) ⇒ Object Also known as: with_debug_mode, with_debug_enabled

Note:

This is equivalent to:
-> enter_debug_mode(halt_core: with_core_halted)
-> ...
-> exit_debug_mode(release_core: with_core_halted)

Runs the given block in debug mode, exiting debug mode upon completion.

Examples:

Perform a write/read-expect operation on dut.core(:reg1)

dut.core.in_debug_mode do
  dut.core.reg(:reg7).write!(0x7)
  dut.core.reg(:reg7).read!(0x7)
end

Parameters:

  • with_core_halted (true, false)

    Indicates if the core should be halted while executing the given blocck. If true, the core will be released upon debug mode exit.



53
54
55
56
57
# File 'lib/origen_arm/cores/cortexm/base_cortexm/cortexm_controller.rb', line 53

def in_debug_mode(with_core_halted: false)
  enter_debug_mode(halt_core: with_core_halted)
  yield
  exit_debug_mode(release_core: with_core_halted)
end

#read_register(reg, options = {}) ⇒ Object

Note:

This doesn't protect from the user copying the register to a different namepace, nor from using the address directly.

Note:

This method will use the toplevel's reg.read!. This is just wraps the write process for certain registers.

Certain registers within the core must be written in certain ways. Override the reg.read! and reg.write! methods to have Origen handle this.

See Also:



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/origen_arm/cores/cortexm/base_cortexm/cortexm_controller.rb', line 101

def read_register(reg, options={})
  if reg_wrapped_by_dcrsr?(reg)
    pp("Reading and Comparing Core Register: DCRDR <- #{reg.name}.data (expecting #{reg.data}") do
      core_reg_to_dcrdr(reg, options)
      reg(:dcrdr).read!(reg.data)
    end
  else
    # Nothing special about this registers. Write it as normal.
    parent.read_register(reg, options)
  end
end

#reg_wrapped_by_dcrsr?(reg) ⇒ Boolean

Note:

Register type indication is done per regster, when adding registers. This method just checks that field.

Checks if the register given is either a general_purpose_register, special_purpose_register, or a floating_point_register.

Read and writes to these regsters are wrapped around the DHRCR and DHRSR registers.

Returns:

  • (Boolean)

Raises:

  • NoRegisterError If reg could not be converted to a register within the selected core.



142
143
144
145
146
147
148
# File 'lib/origen_arm/cores/cortexm/base_cortexm/cortexm_controller.rb', line 142

def reg_wrapped_by_dcrsr?(reg)
  # If reg isn't an Origen register, convert it to one.
  r = reg.is_a?(Origen::Registers::Reg) ? reg : self.reg(reg)
  
  # The register type is a custom field stored in the registers metadata.
  r.meta[:general_purpose_register] || r.meta[:special_purpose_register] || r.meta[:floating_point_register]
end

#write_register(reg, options = {}) ⇒ Object

Note:

This doesn't protect from the user copying the register to a different namepace, nor from using the address directly.

Note:

This method will use the toplevel's reg.write!. This is just wraps the write process for certain registers.

Certain registers within the core must be written in certain ways. Override the reg.read! and reg.write! methods to have Origen handle this.

See Also:



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/origen_arm/cores/cortexm/base_cortexm/cortexm_controller.rb', line 68

def write_register(reg, options={})
  if reg_wrapped_by_dcrsr?(reg)
    # This register write requires a few steps:
    # 1. Write the dcrdr register with the data.
    #
    # 2a. Write the dcrsr[:regwnr] bit to 1 (indicate a write)
    # 2b. Write the regsel bits with the desired register.
    # (The above two take place in a single transaction)
    #
    # Writing the dcrsr will trigger the write to occur. Very important
    # the write to the dcrdr occurs first.
    #
    # This requires a reg_sel lookup.
    pp("Writing Debug Register: #{reg.name} <- #{reg.data.to_hex}") do
      reg(:dcrdr).write!(reg.data)
      reg(:dcrsr).bits(:regwnr).write(1)
      reg(:dcrsr).bits(:reg_sel).write(reg.address) #resolve_regsel(reg))
      reg(:dcrsr).write!
      tester.cycle(repeat: write_debug_register_delay)
    end
  else
    # Nothing special about this registers. Write it as normal.
    parent.write_register(reg, options)
  end
end