I have a function in Main called myFunction and returns a Boolean:
if(this instanceof MyAgent)
return true;
else;
return false;
This function is called in a process block in FactoryAgent, and it simply checks whether the agent that flows through the process block is of type MyAgent. However, when I call this function I get the following error:
Description: Incompatible conditional operand types Main and FactoryAgent.
Inputting this instanceof MyAgent directly in the On enter field of the process block works. How can I correctly refer to this in a function in Main?
this is wrong... the keyword "this" refers to the agent in which you call a function..
If you have a process block in main, this "refers" to main, if you use it in your agent FactoryAgent, "this" refers to FactoryAgent... this means that it will always return false, because "this" is never an instance of MyAgent
Instead you should use the local variable "agent" and change all this to
if(agent instanceof MyAgent)
return true;
else;
return false;
if you want to call this function anywhere, you need to call it with an argument which is the agent that is flowing through the process. If it can be many types of agents, then the argument will be of type Agent, or maybe of type Object.
If you don't know what it means for your function to have an argument, or if you don't know that you can use a local variable called agent, I can explain it, but these are terms that are so fundamental, that I will assume you know
Related
I am trying to add an onClick event to a bunch of buttons on screen that I have Instantiated. But the function I am calling needs parameters. When I put the parameters the code doesn’t run but when I don’t it runs but the function doesn’t do what it is supposed to because it doesn’t have the right parameters. Any ideas?
public void PreviewButtonLook(Image previewPart, Sprite previewSprite)
{
previewPart.GetComponent<Image>().sprite = previewSprite;
}
button.GetComponent<Button>().onClick.AddListener(PreviewButtonLook(previewPart, options[i]);
onClick.AddListener() accepts a delegate of zero parameters.
You can create a zero-parameter anonymous function and pass it as a delegate.
This zero parameter anonymous function can call another function and pass it as many parameters as you want.
button.GetComponent<Button>().onClick.AddListener(delegate {
PreviewButtonLook(previewPart, options[i]);
});
But be aware of function closure.
I am trying to raise an event in Matlab. It is working, but not as i expected. What is going on is that the source object is passed as parameter do the event handler and i can't access my object properties inside the event handler.
Here is my class:
classdef MyClass < handle
properties
Name = 'a';
end
events
Changed
end
methods
function obj = MyClass(current)
if exist('current','var')
addlistener(current,'Changed',#ChangedHandle);
end
end
function obj = Change(obj,value)
notify(obj,'Changed');
end
function obj = ChangedHandle(obj,value)
disp(obj.Name);
end
end
end
These are the command lines to reproduce whats going on:
a = MyClass();
b = MyClass(a);
b.Name = 'b';
a.Change(3);
This is returning "a" and i want it to return "b".
Regards
The listener callback you specify receives details of the object raising the event. The fact that the listener has been created during the creation of a different object is not an intrinsic property of the listener – unless you effectively embed this in the design of your callback.
In your example, #ChangedHandle only works as a callback because it happens to be a method of the class current belongs to. If a and b belonged to different classes the problem would be more obvious: if ChangedHandle was a method only of a, it wouldn't know anything about the Name property of b. And if only a method of b, the listener bound to a would have only the function handle without any reference to the instance b of the class to which ChangeHandle belongs.
As described in the listener callback documentation you can use a method of the specific object instance current as an event listener using the syntax #current.ChangedHandle.
This method then receives callback arguments in the format callbackMethod(obj,src,evnt), so you need to add an argument to the definition of ChangedHandle. The first argument obj will be the instance referenced by current when the listener is created, so the line disp(obj.Name) will then produce the intended result without modification.
The reference to a received by the callback in the example will still be passed to the new callback – this is a fundamental behaviour of listener callbacks – but it will now be accessible from the second argument src.
In your addlistener code you are not telling the listener which object you want to call the method on, so what Matlab does it will apply the listener to the current object since thats all that was passed into the function, you can check this by changing the code to:
addlistener(current,'Changed',#(h,evt)current.ChangedHandle);
if you want it to run the code for the other class b (obj), then you use:
addlistener(current,'Changed',#(h,evt)obj.ChangedHandle);
I'm reading the following guide:
https://colorlesscube.com/uvm-guide-for-beginners/chapter-3-top-block/
In Code 3.2 line 24- run_test();
I realized that it supposed to execute the test, but how it know which test, and how, and why should I write it in the top block.
In Code 4.1 lines 11-14 (https://colorlesscube.com/uvm-guide-for-beginners/chapter-4-transactions-sequences-and-sequencers/):
`uvm_object_utils_begin(simpleadder_transaction)
`uvm_field_int(ina, UVM_ALL_ON)
`uvm_field_int(inb, UVM_ALL_ON)
`uvm_field_int(out, UVM_ALL_ON)
`uvm_object_utils_end
Why should I add the "uvm_field_int" , what would happend if i didn't add them, and what is "UVM_ALL_ON"?
run_test is a helper global function , it calls the run_test function of the uvm_root class to run the test case. There are two ways by which you can pass the test name to the function.The first is via the function argument and the second is via a command line argument. The command line argument takes precedence over the test name passed via the function argument.
+UVM_TESTNAME=YOUR_TEST_NAME
run_test("YOUR_TEST_NAME");
run_test function in the uvm_root uses the factory mechanism to create the appropriate instance of the umm_test class and so the test case must register itself with the factory using the macro `uvm_component_utils for the factory mechanism (create_component_by_name) to function.
class YOUR_TEST_NAME extends umm_test ;
// register the class with the factory
// so that run_test can find this class when the
// string test_name is passed to it.
`uvm_component_utils(YOUR_TEST_NAME)
.....
endclass
The run_test function then kicks of the uvm_phases (..,build_phase,connect_phase,...) starting the uvm portion of the simulation. There should be no time ticks consumed before the run_phase starts , so it is essential that run_test case is called in the initial block itself. Also we want the uvm and test bench to be ready to drive and receive data as soon as the RTL is ready for which it is essential that we start the run_test at the earliest. Any delay in doing so will generate an error.
`uvm_field_int/uvm_field_object/.. are called field automation macros. They are not mandatory in the class definition and are provided as a helper macros to ease the use of many common/routine functions of the uvm_object. Examples of thse functions in uvm_object are - copy,compare,pack,unpack,print, etc and these macros generate code to automatically use these functions.
If you are not using the uvm_object common functions leaving out these macros from the class definition will not produce any errors.
In case you implement you own version of the common operations you can also leave out these macros from the class.
UVM_ALL_ON - enables all functions like compare/copy/... to be implemented for the particular field.
link with examples -
http://www.testbench.in/UT_04_UVM_TRANSACTION.html
For example the uvm_object has a compare function which compare two instances of the same class and return true if all the variables in the class are equal.
virtual function bit do_compare( uvm_object rhs, uvm_comparer comparer );
.....
// return 1 if all the variables match
return ( super.do_compare( rhs, comparer ) &&
this.var_1 == rhs.var_1 &&
this.var_2 == rhs.var_2 &&
......
this.var_n == rhs.var_n );
endfunction: do_compare
// use in main code
if ( new_class.compare(old_classs) )
...
//instead of
if ( new_class.var1 == old_class.var1 && new_class.var2 == old_class.var2 && ... new_class.varn == old_class.varn )
...
The above compare has to be written for each class and updated and maintained for every new variable that is added to the class. This could become error prone as newer variables are added. A similar process has to be followed for all the standard functions uvm_object provides.
The field automation macro generates function to address all these functionality automatically. So doing a do_print for a class with the macros will print out all the fields without explicitly writing any code for it.
// compare/print/.. functions for class simpleadder_transaction are provided by using `uvm_field_int macro.
`uvm_object_utils_begin(simpleadder_transaction)
`uvm_field_int(ina, UVM_ALL_ON)
`uvm_object_utils_end
BUT a word of caution , the use of these macros are discouraged as they add a significant amount of code into the class.. Most of these functions may not be needed by the class yet they get generated by default.
run_test is defined in the documentation (link) as:
virtual task run_test (
string test_name = ""
)
So, in principle, you can state there the test name as a string. But what's usually done is to pass it in the command line of your simulator using the argument: +UVM_TESTNAME=TEST_NAME
The uvm_object macros are a bit more complicated. They generate several methods and more importantly they register the object in the UVM factory, which is what makes them necessary (at least if you are using, as you should, the factory to create them). Citing from the UVM Class Reference documentation (Section 20.2 Component and Object Macros):
Simple (non-parameterized) objects use the uvm_object_utils* versions,
which do the following:
Implements get_type_name, which returns TYPE as a string
Implements create, which allocates an object of type TYPE by calling its constructor with no arguments. TYPE’s constructor, if
defined, must have default values on all it arguments.
Registers the TYPE with the factory, using the string TYPE as the factory lookup string for the type.
Implements the static get_type() method which returns a factory proxy object for the type.
Implements the virtual get_object_type() method which works just like the static get_type() method, but operates on an already
allocated object.
I have a class:
class Hello {
function doSomething(&$reference, $normalParameter) {
// do stuff...
}
}
Then I have a controller:
class myController {
function goNowAction() {
$hello = new Hello();
$var = new stdClass();
$var2 = new stdClass();
$bla = $hello->doSomething($var, $var2);
}
}
The "goNow" action I call using my tests like so:
$this->dispatch('/my/go-now');
I want to mock the "doSomething" method so it returns the word "GONOW!" as the result. How do I do that?
I've tried creating a mock
$mock = $this->getMock('Hello ', array('doSomething'));
And then adding the return:
$stub->expects($this->any())
->method('discoverRoute2')
->will($this->returnValue("GONOW!"));
But I'm stumped as to how to hook this up to the actual controller that I'm testing. What do I have to do to get it to actually call the mocked method?
You could create a mock for the reference, or if it is just a simple reference as your code shows, send a variable. Then the normal mock call may be called and tested.
$ReferenceVariable= 'empty';
$mock = $this->getMock('Hello ', array('doSomething'));
$stub->expects($this->any())
->method('discoverRoute2')
->will($this->returnValue("GONOW!"));
$this->assertEquals('GONOW!', $stub->doSomething($ReferenceVariable, 'TextParameter'));
Your example code does not explain your problem properly.
Your method allows two parameters, the first being passed as a reference. But you create two objects for the two parameters. Objects are ALWAYS passed as a reference, no matter what the declaration of the function says.
I would suggest not to declare a parameter to be passed as a reference unless there is a valid reason to do so. If you expect a parameter to be a certain object, add a typehint. If it must not be an object, try to avoid passing it as a reference variable (this will lead to confusing anyways, especially if you explicitly pass an object as a reference because everybody will try to figure out why you did it).
But your real question is this:
But I'm stumped as to how to hook this up to the actual controller that I'm testing. What do I have to do to get it to actually call the mocked method?
And the answer is: Don't create the object directly in the controller with new Hello. You have to pass the object that should get used into that controller. And this object is either the real thing, or the mock object in the test.
The way to achieve this is called "dependency injection" or "inversion of control". Explanaitions of what this means should be found with any search engine.
In short: Pass the object to be used into another object instead of creating it inside. You could use the constructor to accept the object as a parameter, or the method could allow for one additional parameter itself. You could also write a setter function that (optionally) gets called and replaces the usual default object with the new instance.
In google io 2011, David Chandler mentioned that you can chain different request context by using append() method,but in practice, I don't know how to chain them up while they have different receiver,using to() and then fire()?
Please help.
There are two kinds of receivers: the ones bound to each method invocation (that you pass to the Request's to() method), and the context-level one (that you pass to the RequestContext's fire() method). The Request's fire(Receiver) method is a short-hand for to(receiver).fire(), i.e. it binds the Receiver to the method.
The method-level receivers depend on the method only, their generic parameterization depends on the method's return value (the generic parameterization of the Request or InstanceRequest), so whether you append() several RequestContexts together changes absolutely nothing.
The context-level receiver is always parameterized with Void. When you append() contexts together, they actually form a single context with several interfaces, so you only call fire() once, on any one of the appended contexts.
Now let's go back to the basics: without using append(), you can only batch together calls for methods that are declared on the context interface. If you have two distinct context interfaces you want to use, you have to make two fire(), i.e. two HTTP requests. The introduction of append() allows you to batch together calls for methods declared on any context interface: simply append a context to another one and the calls on both contexts will be batched together in the same HTTP request, triggered by a unique fire() on any one of the context being appended.
Now into the technical details: internally, a context is nothing more than a thin wrapper around a state object. When you edit() or create() a proxy, you add it to the internal state, and when you call a service method, the method name (actually, its obfuscated token) and the arguments are captured and pushed to the state as well. When you append() a context, you're only making it share its internal state with the one of the context you append it to. That way, when you call a service method on the appended context, its pushed on the exact same state as the one of the other context, and when you fire() any one of them, the state is serialized into a single HTTP request.
Note that, to append a context, its own internal state has to be empty, otherwise an exception will be raised, as the state would be thrown away to be replaced by the one of the other context.
In brief, and in practice:
FirstContext first = rf.first();
SomeProxy proxy = first.create(SomeProxy.class);
...
SecondContext second = first.append(rf.second());
OtherProxy other = second.create(OtherProxy.class);
other.setSome(proxy);
...
second.saveAndReturnSelf(other).to(new Receiver<OtherProxy>() {
...
});
...
first.fire();
Note that the line that creates and appends the second context could equally be written:
SecondContext second = rf.second();
first.append(second);
The append method returns its argument as a convenience, but it's really the same value you passed as the argument. This is only to allow writing the one-liner above, instead of being forced to use the two-liner.