Sub_block base_address override? - origen-sdk

Is there a way to assign a different base_address to the sub_blocks of a sub_block?
I have a case where I have something like this:
dut.rb:
sub_block ipBlock base_address: 0x11000000
and so the registers at this level all start with 0x110000000
But ipBlock also has its own sub_blocks:
ipblock.rb:
sub_block subIPBlock base_address: 0x0
with its own registers that due to an interface difference require a 0 base_address.
Unfortunately, when I add registers to subIPBlock they still have the base address of the top-level ipBlock:
sub_ipblock.rb:
add_reg :reg0, 0x0, 16, reset: 0xFFFF ...
Is there is a way to easily reassign the base address of the sub_block of a sub_block?

I believe you can use sub-block domains to achieve what you want.
sub_block :subx2, class_name: "SubX", base_address: { ips: 0x2000_0000, ahb: 0x3000_0000 }
dut.subx1.reg1.address(domain: :ips) # => 0x2000_0200
dut.subx1.reg1.address(domain: :ahb) # => 0x3000_0200
regards

In addition to the other answer, also note that reg.offset will return the block relative address, which it sounds like you want here.
All Origen drivers should override the register's address when an :address option is given, so within your model you could implement a read/write register method to add an :address option:
def write_register(reg, options = {})
if your_criteria_to_use_local_address
options[:address] = reg.offset
end
dut.write_register(reg, options) # Handover for original write
end
You could also force/override the base address within your model by implementing the following method:
def reg_base_address(options = {})
0
end
Finally, note that when using the domains per #rchitect-of-info's answer, you can define two domains when you instantiate a parent sub-block, then when you instantiate a child of that sub-block you can pick which of the available domains it is assigned to.
See this example from the documentation linked to in the other answer:
$dut.subx2.suby1.reg1.address # => 0x2000_0300
$dut.subx2.suby2.reg1.address # => 0x3000_0300

Related

Confusion About Implementing LeafSystem With Vector Output Port Correctly

I'm a student teaching myself Drake, specifically pydrake with Dr. Russ Tedrake's excellent Underactuated Robotics course. I am trying to write a combined energy shaping and lqr controller for keeping a cartpole system balanced upright. I based the diagram on the cartpole example found in Chapter 3 of Underactuated Robotics [http://underactuated.mit.edu/acrobot.html], and the SwingUpAndBalanceController on Chapter 2: [http://underactuated.mit.edu/pend.html].
I have found that due to my use of the cart_pole.sdf model I have to create an abstract input port due receive FramePoseVector from the cart_pole.get_output_port(0). From there I know that I have to create a control signal output of type BasicVector to feed into a Saturation block before feeding into the cartpole's actuation port.
The problem I'm encountering right now is that I'm not sure how to get the system's current state data in the DeclareVectorOutputPort's callback function. I was under the assumption I would use the LeafContext parameter in the callback function, OutputControlSignal, obtaining the BasicVector continuous state vector. However, this resulting vector, x_bar is always NaN. Out of desperation (and testing to make sure the rest of my program worked) I set x_bar to the controller's initialization cart_pole_context and have found that the simulation runs with a control signal of 0.0 (as expected). I can also set output to 100 and the cartpole simulation just flies off into endless space (as expected).
TL;DR: What is the proper way to obtain the continuous state vector in a custom controller extending LeafSystem with a DeclareVectorOutputPort?
Thank you for any help! I really appreciate it :) I've been teaching myself so it's been a little arduous haha.
# Combined Energy Shaping (SwingUp) and LQR (Balance) Controller
# with a simple state machine
class SwingUpAndBalanceController(LeafSystem):
def __init__(self, cart_pole, cart_pole_context, input_i, ouput_i, Q, R, x_star):
LeafSystem.__init__(self)
self.DeclareAbstractInputPort("state_input", AbstractValue.Make(FramePoseVector()))
self.DeclareVectorOutputPort("control_signal", BasicVector(1),
self.OutputControlSignal)
(self.K, self.S) = BalancingLQRCtrlr(cart_pole, cart_pole_context,
input_i, ouput_i, Q, R, x_star).get_LQR_matrices()
(self.A, self.B, self.C, self.D) = BalancingLQRCtrlr(cart_pole, cart_pole_context,
input_i, ouput_i,
Q, R, x_star).get_lin_matrices()
self.energy_shaping = EnergyShapingCtrlr(cart_pole, x_star)
self.energy_shaping_context = self.energy_shaping.CreateDefaultContext()
self.cart_pole_context = cart_pole_context
def OutputControlSignal(self, context, output):
#xbar = copy(self.cart_pole_context.get_continuous_state_vector())
xbar = copy(context.get_continuous_state_vector())
xbar_ = np.array([xbar[0], xbar[1], xbar[2], xbar[3]])
xbar_[1] = wrap_to(xbar_[1], 0, 2.0*np.pi) - np.pi
# If x'Sx <= 2, then use LQR ctrlr. Cost-to-go J_star = x^T * S * x
threshold = np.array([2.0])
if (xbar_.dot(self.S.dot(xbar_)) < 2.0):
#output[:] = -self.K.dot(xbar_) # u = -Kx
output.set_value(-self.K.dot(xbar_))
else:
self.energy_shaping.get_input_port(0).FixValue(self.energy_shaping_context,
self.cart_pole_context.get_continuous_state_vector())
output_val = self.energy_shaping.get_output_port(0).Eval(self.energy_shaping_context)
output.set_value(output_val)
print(output)
Here are two things that might help:
If you want to get the state of the cart-pole from MultibodyPlant, you probably want to be connecting to the continuous_state output port, which gives you a normal vector instead of the abstract-type FramePoseVector. In that case, your call to get_input_port().Eval(context) should work just fine.
If you do really want to read the FramePoseVector, then you have to evaluate the input port slightly differently. You can find an example of that here.

Scapy bind_layers using a layer condition outside the binding scope

I'm new to Scapy so maybe this is written down somewhere but I can't find the answer.
I'm trying to create a custom packet dissector but in order to bind specific layers to each other I need to do it on condition of a value in a deeper layer.
I have a minimum of three layers above the RTP layer but the number of 2nd and third layers is determined by a value in the first layer.
Cust1 holds the number of Cust2 layers that will follow. Each Cust2 layer will have a corresponding Cust3 layer to match with it at the end of the chain of Cust2 layers. I've shown an example below where I've used 2a/2b/2c and 3a/3b/3c just to indicate that the numbers are the same layer type but chained together.
i.e
If Cust1 holds a value of one(1) then:
UDP / RTP / Cust1 / Cust2a / Cust3a
if Cust1 holds a value of two(2):
UDP / RTP / Cust1 / Cust2a/Cust2b / Cust3a/Cust3b
if Cust1 holds a value of three(3):
UDP / RTP / Cust1 / Cust2a/Cust2b/Cust2c / Cust3a/Cust3b/Cust3c
etc...
So how do I reference Cust1 for bindings that are further along in the chain?
bind_layers(RTP, Cust1)
bind_layers(Cust1, Cust2a)
bind_layers(Cust2a, Cust2b, {conditional REF_to_Cust1.value})
bind_layers(Cust2b, Cust2c, {conditional REF_to_Cust1.value})
# etc...
Please tell me I don't have to create a custom layer for each scenario and use that to get my desired result.
It is not easily possible if you seperate your packet in several layers, it is easily achieveable using some special fields. (You could actually use guess_payload_class but it's more of a pain...)
Have a look at PacketListField or at the adequate documentation.
This is the general idea:
class Cust2(Packet):
...
class Cust3(Packet):
...
class Cust1(Packet):
fields_desc = [
ByteField("number_of_cust2", 0),
...,
PacketFieldList("cust2s", [], Cust2, count_from=lambda pkt: pkt.number_of_cust2),
PacketFieldList("cust3s", [], Cust3, count_from=lambda pkt: pkt.number_of_cust2),
]

Does origen_testers V93K support test method libraries with different classes?

We have custom test method libraries that support a couple different test method classes. For example:
test93k.common.Functional
test93kcustomext.common.Functional
Would I need to create different test method libraries in our test interface using the add_tml method or can they both exist in the same test method library? In the end, we need the correct class to show up in the generated flow as so:
testmethods
tm_jtag_regular:
testmethod_class = "test93k.common.Functional";
tm_jtag_extension:
testmethod_class = "test93kcustomext.common.Functional";
What controls the test that goes above?
regards
You can apply a class_name: option to both the library and the individual tests, so you could try:
add_tml :my_tml,
class_name: '', # Try setting this to nothing
functional: {
class_name: 'test93k.common.Functional',
},
functional_ext: {
class_name: 'test93kcustomext.common.Functional',
}
There's a chance that the final name might end up with a leading ., though it should be a simple patch to make it inhibit that if the TML class name is blank.
Defining them as two separate TMLs would definitely work too, and is probably how it should be handled:
add_tml :regular,
class_name: 'test93k.common',
functional: {
class_name: 'Functional', # May not even need this
}
add_tml :ext,
class_name: 'test93kcustomext.common',
functional: {
class_name: 'Functional', # May not even need this
}
See here for more - https://origen-sdk.org/origen/guides/program/v93k/#Custom_Test_Methods

Origen::Parameter sets getting erased upon $dut re-init

I create many test interface parameters during the $dut initialization. The app inits the model in either 'load' or 'import' mode, as we get many sources of info from 3rd parties. For parameters, the source is native Ruby so regardless of the init method (load or import) the code is required like this:
send modeling_method, model_path # load_params or import_params
Here is that method(s):
def load_params(path)
Origen.log.info("PPEKit: Modeling parameters from #{path}")
require path.to_s.chomp('.rb')
Origen.log.info("PPEKit: Modeling of parameters complete")
end
alias_method 'import_params', 'load_params'
Here is the content of the file required above:
Origen.top_level.define_params :default do |params|
params.bist.override = 1
params.bist.lev_equ_set = 1
params.bist.lev_spec_set = 1
params.bist.levset = 1
params.bist.seqlbl = 'mbist_cpu_hr_vnom_burst'
params.bist.override_tim_spec_set = 'bist_25Mhz'
params.bist.override_timset = '1,1,1,1,1,1,1,1'
params.bist.site_control = 'parallel:'
params.bist.site_match = 2
end
I can see them at the end of my $dut initialization during execution of the command 'origen p myflowfile.rb':
[5] pry(#<PPEKit::Product>)> $dut.params
=> {:bist=>
{:override=>1,
:lev_equ_set=>1,
:lev_spec_set=>1,
:levset=>1,
:seqlbl=>"mbist_cpu_hr_vnom_burst",
:override_tim_spec_set=>"bist_25Mhz",
:override_timset=>"1,1,1,1,1,1,1,1",
:site_control=>"parallel:",
:site_match=>2}}
However, when Origen transitions to the test interface code, the params are not accessible:
[1] pry(#<STP::Interface>)> $dut.params
=> #<Origen::Parameters::Missing:0x002aaab22dc378
#owner=<Model/Controller: PPEKit::Product:23456337817000/PPEKit::ProductController:23456355062960>>
I can, however, see other parts of the $dut model such as pins and sub_blocks:
[2] pry(#<STP::Interface>)> $dut.sub_blocks
=> {"block0"=><Model: PPEKit::Product::Block0:23456336916760>,
"block1"=><Model: PPEKit::Product::Block1:23456336907380>,
"block2"=><Model: PPEKit::Product::Block2:23456336841100>,
It just seems like they are getting erased sometime between the model init and the test flow generation. So I put a breakpoint in the 'on_load_target' callback, and saw different results each time the breakpoint was hit. On the first break, the params were there and on subsequent breaks they were not.
75: def on_load_target
=> 76: binding.pry
77: to_origen(path: vendor_path.to_s, instantiate_level: :sub_block) if #import
78: end
[1] pry(#<PPEKit::Product>)> $dut.params
=> {:bist=>
{:override=>1,
:lev_equ_set=>1,
:lev_spec_set=>1,
:levset=>1,
:seqlbl=>"mbist_ccx_hr_vnom_burst",
:override_tim_spec_set=>"bist_25Mhz",
:override_timset=>"1,1,1,1,1,1,1,1",
:site_control=>"parallel:",
:site_match=>2}}
[2] pry(#<PPEKit::Product>)>
Frame number: 0/25
From: /users/user/origen/ppekit/lib/ppekit/product.rb # line 76 PPEKit::Product#on_load_target:
75: def on_load_target
=> 76: binding.pry
77: to_origen(path: vendor_path.to_s, instantiate_level: :sub_block) if #import
78: end
[1] pry(#<PPEKit::Product>)> $dut.params
=> #<Origen::Parameters::Missing:0x002aaab9f3ad48
#owner=<Model/Controller: PPEKit::Product:23456377300040/PPEKit::ProductController:23456379739240>>
I believe there could be 2 issues here:
1) The repeated initialization of the $dut during test flow generation, documented here
2) The emptying of the parameter set hash, which is due to issue #1 (and some Parameter set initialization code
I believe it has something to do with the parameter #owner being defined as the $dut instance during the parameter definition and #owner being re-defined as the $dut ProductController instance on subsequent queries of the parameters.
thx
The problem here is that the parameters are ultimately getting loaded by calling require 'some_file.rb'.
Whenever the target is internally re-loaded, Ruby hits the line again but does not do anything since it knows that it has already required that file and effectively skips over that line.
Changing it to load 'some_file.rb' will force it to execute the file every time.

LocalizedPVSystem values

i have the following verified set of values for central London in 30min intervals (2015-2016):
Direct NI;Diffuse NI;Reflected;Global NI;Direct Horiz;Diffus Horiz;Global Horiz;Top of Atmosphere
this data is from soda-pro.com. the wind_speed and temp_air data is as well verified.
trying to create a simple pv generation model, i am not sure which values should be fed into the total_irrad function.
for [dni, ghi, dhi] i've tried [Direct NI, Global Horiz, Direct Horiz] but the values make no sense (556kWh yearly for a 1kW system).
replacing the Direct NI with Global NI resulted 765 kWh/year for the same system - a bit more reasonable i think - but i'm not sure if that's correct.
advice please?
I believe "POA global" should be fed to the system. You can calculate POA using get_irradiance function from pvsystem.
reference : link
DNI = Direct Normal Irradiance
GHI = Global Horizontal Irradiance
DHI = Diffuse Horizontal Irradiance
For your dataset, [dni, ghi, dhi] = [Direct NI, Global Horiz, Diffus Horiz]

Resources