Where to use uvm_blocking_put_port and uvm_analysis_port? - uvm

What is the difference between port and analysis port ?
Where to use uvm_blocking_put_port and where to use uvm_analysis_port ?
What is advantage of uvm_analysis_port over uvm_blocking_put_port ?

Port connection is used to connect two independent blocks(components).
Both uvm_blocking_put_port and uvm_analysis_port used to transfer data from producer to consumer.
(1) uvm_blocking_put_port:
Used for data transfer from a single producer to a single consumer.
(2) uvm_analysis_port:
Used for data transfer from a single producer to a single consumer or multiple consumers.
Advantage for this analysis port is that a user can transfer data from a single producer to multiple consumers that is not archived with help of uvm_blocking_put_port.
This thing is also explained in the figure.
Here I provide sample code to get more clarity for uvm_blocking_put_port and uvm_analysis_port.
This image explain use of uvm_blocking_put_port
Remember: Port connection is used to connect two or more independent component.
(1) uvm_blocking_put_port EXAMPLE.
class transaction extends uvm_sequence_item;
`uvm_object_utils(transaction);
rand int unsigned a;
rand int unsigned b;
function new(string name ="");
super.new(name);
endfunction
endclass
class producer extends uvm_component;
`uvm_component_utils(producer);
transaction tr_inst;
uvm_blocking_put_port #(transaction) produce_to_consumer_p;
function new(string name ="",uvm_component parent);
super.new(name,parent);
produce_to_consumer_p = new("produce_to_consumer_p",this);
tr_inst = new("tr_inst");
endfunction
task run_phase(uvm_phase phase) ;
super.run_phase(phase);
phase.raise_objection(this);
//tr_inst.randomize();
`uvm_info(get_full_name(),"Write the data from PRODUCER",UVM_LOW)
tr_inst.a = 10; tr_inst.b = 20;
produce_to_consumer_p.put(tr_inst);
phase.drop_objection(this);
endtask
endclass
class consumer extends uvm_component;
`uvm_component_utils(consumer);
uvm_blocking_put_imp#(transaction,consumer) put_imp;
//transaction tr_inst;
function new(string name ="",uvm_component parent);
super.new(name,parent);
put_imp = new("put_imp",this);
endfunction
function void put(transaction tr_inst);
`uvm_info(get_full_name(),"Got the data in CONSUMER",UVM_LOW);
`uvm_info(get_full_name(),$sformatf("the value of a %0d and b is %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
endclass
class env extends uvm_component;
`uvm_component_utils(env);
producer p_inst;
consumer c_inst;
function new(string name="",uvm_component parent);
super.new(name,parent);
p_inst = new("p_inst",this);
c_inst = new("c_inst",this);
endfunction
function void connect();
p_inst.produce_to_consumer_p.connect(c_inst.put_imp);
endfunction
endclass
module main();
env env_inst;
initial
begin
env_inst = new("env_inst",null);
run_test();
end
endmodule
This image gives explanation of uvm_analysis_port
(2) uvm_analysis_port EXAMPLE
class transaction extends uvm_sequence_item;
`uvm_object_utils(transaction);
rand int unsigned a;
rand int unsigned b;
function new(string name ="");
super.new(name);
endfunction
endclass
class producer extends uvm_component;
`uvm_component_utils(producer);
transaction tr_inst;
uvm_analysis_port #(transaction) produce_to_consumer_p;
function new(string name ="",uvm_component parent);
super.new(name,parent);
produce_to_consumer_p = new("produce_to_consumer_p",this);
tr_inst = new("tr_inst");
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(this);
// tr_inst.randomize();
`uvm_info(get_full_name(),"Write the data from PRODUCER",UVM_LOW);
tr_inst.a = 10; tr_inst.b = 20;
produce_to_consumer_p.write(tr_inst);
phase.drop_objection(this);
endtask
endclass
class consumer_1 extends uvm_component;
`uvm_component_utils(consumer_1);
uvm_analysis_imp#(transaction,consumer_1) write_imp_1;
function new(string name ="",uvm_component parent);
super.new(name,parent);
write_imp_1 = new("write_imp_1",this);
endfunction
function void write(transaction tr_inst);
`uvm_info(get_full_name(),"Got the data in CONSUMER_1",UVM_LOW);
`uvm_info(get_full_name(),$sformatf("The value of a = %0d and b = %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
endclass
class consumer_2 extends uvm_component;
`uvm_component_utils(consumer_2);
uvm_analysis_imp#(transaction,consumer_2) write_imp_2;
function new(string name ="",uvm_component parent);
super.new(name,parent);
write_imp_2 = new("write_imp_2",this);
endfunction
function void write(transaction tr_inst);
`uvm_info(get_full_name(),"Got the data in CONSUMER_2",UVM_LOW);
`uvm_info(get_full_name(),$sformatf("The value of a = %0d and b = %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
endclass
class consumer_3 extends uvm_component;
`uvm_component_utils(consumer_3);
uvm_analysis_imp#(transaction,consumer_3) write_imp_3;
function new(string name ="",uvm_component parent);
super.new(name,parent);
write_imp_3 = new("write_imp_3",this);
endfunction
function void write(transaction tr_inst);
`uvm_info(get_full_name(),"Got the data in CONSUMER_3",UVM_LOW);
`uvm_info(get_full_name(),$sformatf("The value of a = %0d and b = %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
endclass
class env extends uvm_component;
`uvm_component_utils(env);
producer p_inst;
consumer_1 c_inst_1;
consumer_2 c_inst_2;
consumer_3 c_inst_3;
function new(string name="",uvm_component parent);
super.new(name,parent);
p_inst = new("p_inst",this);
c_inst_1 = new("c_inst_1",this);
c_inst_2 = new("c_inst_2",this);
c_inst_3 = new("c_inst_3",this);
endfunction
function void connect();
p_inst.produce_to_consumer_p.connect(c_inst_1.write_imp_1);
p_inst.produce_to_consumer_p.connect(c_inst_2.write_imp_2);
p_inst.produce_to_consumer_p.connect(c_inst_3.write_imp_3);
endfunction
endclass
module main();
env env_inst;
initial
begin
env_inst = new("env_inst",null);
run_test();
end
endmodule

Related

ctypes: Minimal type checking in object oriented C API

I am trying to wrap to python3 a very simple Object Oriented C-API. This basically follow the same pattern as:
Developing C wrapper API for Object-Oriented C++ code or,
Wrapping C++ class API for C consumption
So basically my issue is as follow, I have the following input API:
$ cat api.h
/* ns::a */
typedef struct ns_a ns_a;
ns_a* ns_a_create();
void ns_a_delete(ns_a* a);
bool ns_a_execute(ns_a* a);
/* ns::b */
typedef struct ns_b ns_b;
ns_b* ns_b_create();
void ns_b_delete(ns_b* b);
bool ns_b_run(ns_b* b);
Which I then wrap using the following steps:
class _TypeSafeHandle:
def __init__(self, ptr):
self._as_parameter_ = ptr
#classmethod
def from_param(cls, obj):
if obj.__class__ != cls:
raise ValueError(f"Not a {obj.__class__.__name__} reference")
if not obj._as_parameter_:
raise ValueError("Passing undefined instance")
return obj
#final
class _A(_TypeSafeHandle):
""" for library author, not intended to be exposed publicly """
def __init__(self, ptr):
super().__init__(ptr)
#final
class _B(_TypeSafeHandle):
def __init__(self, ptr):
super().__init__(ptr)
Given the type definition I can now expose the C-API as:
# a
ns_a_create = _func('ns_a_create', c_void_p, None, _check_ns_a)
ns_a_delete = _func('ns_a_delete', None, [_A])
ns_a_execute = _func('ns_a_execute', c_bool, [_A])
# b
ns_b_create = _func('ns_b_create', c_void_p, None, _check_ns_b)
ns_b_delete = _func('ns_b_delete', None, [_B])
ns_b_run = _func('ns_b_run', c_bool, [_B])
Using:
def _func(name, restype, argtypes, errcheck):
func = getattr(_lib, name)
func.restype = restype
func.argtypes = argtypes
func.errcheck = errcheck
return func
and:
def _check_ns_a(result, _func, _args):
if result is None:
raise MemoryError("internal memory allocation failure")
if type(result) != int:
raise TypeError("Expecting int value for pointer")
return = _A(c_void_p(result))
and
def _check_ns_b(result, _func, _args):
if result is None:
raise MemoryError("internal memory allocation failure")
if type(result) != int:
raise TypeError("Expecting int value for pointer")
return = _B(c_void_p(result))
At this step, I can now expose the class A to my user:
class A:
def __init__(self):
self._a = ns_a_create()
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
ns_a_delete(self._a)
def execute(self):
ret = ns_a_execute(self._a)
if not ret:
raise ValueError("Could not execute")
I'd like to keep the intermediate _A and _B class as implementation detail for the library author (avoid shooting in the foot passing wrong instance to wrong delete function). I find it more readable than declaring a forward declared class A:
class A: # forward declaration
pass
# _func declaration with type `A` instead of `_A`
class A:
# actual implementation detail
So my question is: is there a way to reduce code redundancy in between _A and _B ? Is there a way to reduce code redundancy in between _check_ns_a and _check_ns_b ?

Godot/GdScript How to instantiate a class from a static function?

I have 2 scripts:
A.gd
class_name A
var v = 0
func _init(v_):
v = v_
B.gd
class_name B
var A = preload("res://A.gd")
static func Add(a1:A, a2:A):
return A.new(a1.v + a2.v)
I don't understand why I have this error while I'm typing:
res://B.gd:6 - Parse Error: Can't access member variable ("A") from a static function.
Apparently, I can't instantiate A from a static function. If I remove static, there are no more errors. What am I doing wrong? How can I instantiate A from a static function?
There are no static variables in Godot. Thus that var A is not a static variable. And thus it is not available from a static function.
On the other hand, if you gave a name to your class with class_name - which you did - then that class name exist everywhere. Remove var A.

How to fetch remaining energy of all neighbor nodes in Unetstack?

I have developed an energy model that can be loaded for every node present in the network. This model calculates transmitting and receiving energy.
Now what I want to do is if a node request all it's neighboring nodes then those neighbor nodes should reply back by sending their remaining energy values so that the node can decide which neighbor has higher energy level.
How to implement this and how that requesting node will fetch all energy values received
from various neighbor nodes?
This is my energy model :
import org.arl.fjage.*
import org.arl.unet.*
import org.arl.unet.phy.*
import java.math.*
import Java.util.*
class EnergyModel extends UnetAgent {
int neighbor, addr
float neighbor_distance;
def ranging
def init_energy = 10
def dist
def data
def depth
def C = 1.3312e-9 // empirical constant
static def Tot_bits
def fr = 10 //carrier freq.(Khz)
def d = 0.036*Math.pow(fr,1.5) //Thorp's constant
static def source
static HashMap<Integer, Integer[]> map = new HashMap<>();
def sum=0.0,avg=0.0,count=0;
public void startup() {
AgentID phy = agentForService(Services.PHYSICAL);
subscribe (topic(phy));
ranging = agentForService Services.RANGING;
subscribe topic(ranging);
def nodeInfo = agentForService Services.NODE_INFO;
addr = nodeInfo.address;
depth = nodeInfo.location[2]
map.put(addr, nodeInfo.location);
}
public void processMessage(Message msg) {
if (msg instanceof DatagramFailureNtf){
System.out.println "\n\tDatagramFailureNtf occured!!\nt"+msg.toString()
println "\n\t BadFrameNtf occured !!!!\n\t"+msg.toString()
}
if (msg instanceof DatagramNtf && msg.protocol == Protocol.DATA) {
count++
neighbor = msg.from;
source = msg.from;
data = msg.getData()
int[] loc1 = map.get(source)
int[] loc2 = map.get(msg.getTo())
def x = loc1[0] - loc2[0]
def y = loc1[1] - loc2[1]
def distance = Math.sqrt((x)*(x) +(y)*(y));
def bits=32
Tot_bits = bits*data.size()
System.out.println "\n\tNumber of bits sent :"+Tot_bits
dist = distance/1000.0 // converting the distance in Km.
BigDecimal Tx_EG = new BigDecimal("1"); // Or BigInteger.ONE
Tx_EG = Tx_EG.multiply(BigDecimal.valueOf(Tot_bits*50e-9+ Tot_bits*
(0.001)*dist*(depth*-0.001)*C*Math.pow(Math.E,d*dist)));
init_energy = init_energy - Tx_EG ;
sum = sum + Tx_EG
avg = sum/count
String value = String.valueOf(Tx_EG.doubleValue());
System.out.println '\n\tTransmission Energy : '+value+" Joules";
System.out.println '\tRemaining Energy : '+(init_energy)
File file = new File("I:\\out.txt")
def text = file.getText()
System.out.println "ENERGY: -t "+text+" -i "+source+" -d
"+Tot_bits+" -e "+init_energy+" T"
println "ENERGY: -t "+text+" -i "+source+" -d "+Tot_bits+" -e
"+init_energy+" T"
}
if (msg instanceof RxFrameNtf && msg.protocol == Protocol.DATA){
data = msg.getData() // getting data
System.out.println "\tData is :"+data
def bits=32
Tot_bits = bits*data.size() //caculating total number of bits
System.out.println "\tNumber of bits received :"+Tot_bits
BigDecimal Rx_EG = new BigDecimal("1"); // Or BigInteger.ONE
Rx_EG = Rx_EG.multiply(BigDecimal.valueOf(Tot_bits*50e-9));
init_energy = init_energy - Rx_EG ;
String value = String.valueOf(Rx_EG.doubleValue());
System.out.println '\n\tReception Energy : '+value+" Joules";
System.out.println '\tRemaining Energy : '+(init_energy)
System.out.println '\tTime : '+msg.getRxTime()
System.out.println '\tNode ID : '+msg.getTo()
System.out.println "ENERGY: -t "+msg.getRxTime()+" -i
"+msg.getTo()+" -d "+Tot_bits+" -e "+init_energy+" R"
println "ENERGY: -t "+msg.getRxTime()+" -i "+msg.getTo()+" -d
"+Tot_bits+" -e "+init_energy+" R"
}
if (msg instanceof BadFrameNtf){
System.out.println "\n\tBadFrameNtf occured !!!!\n\t"+msg.toString()
println "\n\t BadFrameNtf occured !!!!\n\t"+msg.toString()
}
if (msg instanceof CollisionNtf){
System.out.println "\n\tCollision occured !!!!\n\t"+msg.toString()
println "\n\tCollision occured !!!!\n\t"+msg.toString()
}
}
void setup() {
}
}
You'll need to define application-specific PDUs to request this information and provide this information, and implement your own protocol to respond with appropriate response PDUs when a request PDU is received. See how to write your own application-specific protocols from the ping example (samples/ping folder in the simulator) in the developer's guide.
An alternative would be to expose the energy as an agent parameter for PHY, and request it using the remote access service to use the RemoteParamReq to ask for it.

Difference Between the uvm_analysis ports

Can you please help to understand the functionality and clear difference between:
uvm_analysis_export
uvm_analysis_port
uvm_analysis_imp
I have searched in internet, there are some explanations, like those:
https://verificationacademy.com/forums/uvm/uvmanalysisimp-and-uvmanalysisexport
https://www.vmmcentral.org/uvm_vmm_ik/files3/tlm1/uvm_analysis_port-svh.html
But still I feel that need more explanation. Can someone help please.
uvm_analysis_port's are the publisher, they broadcast transactions
uvm_analysis_imp's are the subscriber, they receive transactions and call a function named 'write' in the class in which they are defined.
uvm_analysis_export's can be more confusing, they are used to expose 'imp' ports at higher level of the hierarchy. For example if you have an agent which contains a component with an analysis_imp and you want to make that 'imp' available at the agent's interface level. In this situation you declare and instantiate the analysis_export in the agent class, then in the connect_phase connect the agent's analysis_export to your internal component's analysis_imp.
Its worth noting, exports are for the subscribing side, but on the publishing side regular uvm_analysis_port's can be used in the same way. So agent's can instantiate analysis_ports and connect them to an internal component's analysis_port.
This is good because it allows you to avoid reaching down into the hierarchy when you are connecting components (which makes maintenance easier):
bad:
bus_agent.internal_monitor.packet_port.connect(checker.ref_model.packet_imp)
good:
bus_agent.packet_port.connect(checker.packet_export)
Its also good to become familiar with the macro uvm_analysis_imp_decl(). It allows you to use more than one analysis_imp in a component.
Advantage for this analysis port is that a user can transfer data from a single producer to multiple consumers that is not archived with help of uvm_blocking_put_port.
This thing is also explained in the figure.
Here I provides sample code to get more clarity for uvm_analysis_port.
Remember: Port connection is used to connect two or more independent component.
This image gives explanation of uvm_analysis_port
uvm_analysis_port EXAMPLE
class transaction extends uvm_sequence_item;
`uvm_object_utils(transaction);
rand int unsigned a;
rand int unsigned b;
function new(string name ="");
super.new(name);
endfunction
endclass
class producer extends uvm_component;
`uvm_component_utils(producer);
transaction tr_inst;
uvm_analysis_port #(transaction) produce_to_consumer_p;
function new(string name ="",uvm_component parent);
super.new(name,parent);
produce_to_consumer_p = new("produce_to_consumer_p",this);
tr_inst = new("tr_inst");
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(this);
// tr_inst.randomize();
`uvm_info(get_full_name(),"Write the data from PRODUCER",UVM_LOW);
tr_inst.a = 10; tr_inst.b = 20;
produce_to_consumer_p.write(tr_inst);
phase.drop_objection(this);
endtask
endclass
class consumer_1 extends uvm_component;
`uvm_component_utils(consumer_1);
uvm_analysis_imp#(transaction,consumer_1) write_imp_1;
function new(string name ="",uvm_component parent);
super.new(name,parent);
write_imp_1 = new("write_imp_1",this);
endfunction
function void write(transaction tr_inst);
`uvm_info(get_full_name(),"Got the data in CONSUMER_1",UVM_LOW);
`uvm_info(get_full_name(),$sformatf("The value of a = %0d and b = %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
endclass
class consumer_2 extends uvm_component;
`uvm_component_utils(consumer_2);
uvm_analysis_imp#(transaction,consumer_2) write_imp_2;
function new(string name ="",uvm_component parent);
super.new(name,parent);
write_imp_2 = new("write_imp_2",this);
endfunction
function void write(transaction tr_inst);
`uvm_info(get_full_name(),"Got the data in CONSUMER_2",UVM_LOW);
`uvm_info(get_full_name(),$sformatf("The value of a = %0d and b = %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
endclass
class consumer_3 extends uvm_component;
`uvm_component_utils(consumer_3);
uvm_analysis_imp#(transaction,consumer_3) write_imp_3;
function new(string name ="",uvm_component parent);
super.new(name,parent);
write_imp_3 = new("write_imp_3",this);
endfunction
function void write(transaction tr_inst);
`uvm_info(get_full_name(),"Got the data in CONSUMER_3",UVM_LOW);
`uvm_info(get_full_name(),$sformatf("The value of a = %0d and b = %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
endclass
class env extends uvm_component;
`uvm_component_utils(env);
producer p_inst;
consumer_1 c_inst_1;
consumer_2 c_inst_2;
consumer_3 c_inst_3;
function new(string name="",uvm_component parent);
super.new(name,parent);
p_inst = new("p_inst",this);
c_inst_1 = new("c_inst_1",this);
c_inst_2 = new("c_inst_2",this);
c_inst_3 = new("c_inst_3",this);
endfunction
function void connect();
p_inst.produce_to_consumer_p.connect(c_inst_1.write_imp_1);
p_inst.produce_to_consumer_p.connect(c_inst_2.write_imp_2);
p_inst.produce_to_consumer_p.connect(c_inst_3.write_imp_3);
endfunction
endclass
module main();
env env_inst;
initial
begin
env_inst = new("env_inst",null);
run_test();
end
endmodule
Here is link which gives you more clarity for analysis port as well as uvm_port.
Link: http://stackoverflow.com/questions/38085875/where-to-use-uvm-blocking-put-port-and-uvm-analysis-port

Dynamic (down)casting in Scala

I'm currently trying to figure out the depths of Scala's type system and Scala reflection.
I have the following example code (my real code is more complex and makes more sense, but boils down to this):
abstract class Node
class Foo extends Node
case class ArrayFoo(var subs : Array[Foo]) extends Foo
case class IntFoo(i : Integer) extends Foo
object Main {
def DoSomething(node : AnyRef) : AnyRef = { // Fix this function?
// do some stuff
node
}
def SetArrayWithReflection(n : Node, a : AnyRef) = {
if (a.isInstanceOf[Array[AnyRef]]) {
val arrayA = a.asInstanceOf[Array[AnyRef]].map(f => DoSomething(f)) // FIX this call?
val getter = n.getClass.getMethods.find(p => p.getName == "subs")
val setter = n.getClass.getMethods.find(p => p.getName == "subs_$eq")
if (setter == None) println("Method not found!") else {
println(f"would need to downcast from ${arrayA.getClass.getComponentType} to ${getter.get.getReturnType.getComponentType}")
setter.get.invoke(n, arrayA) // Error happens here
}
}
}
def main(args : Array[String]) : Unit = {
val my = ArrayFoo(Array(IntFoo(1), IntFoo(2), IntFoo(3)))
val newArray = Array(IntFoo(10), IntFoo(20), IntFoo(30))
SetArrayWithReflection(my, newArray)
my.subs.foreach(f => println(f))
}
}
The output I'm getting is:
would need to downcast from class java.lang.Object to class Foo
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at Main$.SetArrayWithReflection(Main.scala:19)
at Main$.main(Main.scala:27)
at Main.main(Main.scala)
Via reflection, I try to call a method expecting an Array[Object] with an Array[Foo], which obviously has to fail.
My question is: How can I downcast or create a suitable Array for method invocation?
The same code does work for Lists, however. I suppose this is due to type erasure which does not happen on Arrays.
Thanks in advance,
Velines
You can't downcast an Array[Object] to Array[Foo]. The simplest way to create the array you need is
val arrayFoo = Array.ofDim[Foo](arrayA.length)
System.arraycopy(arrayA, 0, arrayFoo, 0, arrayA.length)
See System.arraycopy.

Resources