Legal syntax for parameterized interface - system-verilog

I have a interface definition for a parameterized interface as follows :
interface A#(parameter adr=64,parameter data=128,parameter enable=1)(input clk, input rst);
endinterface
Now, can i declare something like ? Is this legal ?
A#(,,0) A0(clk,rst);
I did not find any such examples in the 1800-2012 SV LRM, so I was wondering about the legality of this syntax before I contact the EDA vendor. One such major tool vendor works perfectly fine but another major vendor complains about this - The error specifically being
near ",": syntax error, unexpected ','.

I don't know whether it's legal. Two simulators rejected it and one didn't (probably the same one as you). But you could
i) rearrange the order of the parameters:
interface A#(parameter enable=1, parameter adr=64,parameter data=128)(input clk, input rst);
endinterface
A #(0) a (.clk, .rst);
ii) use named mapping:
A #(.enable(0)) a (.clk, .rst);

You cannot skip over parameter overrides in an ordered list. It's illegal syntax according to the BNF:
list_of_parameter_assignments ::=
ordered_parameter_assignment { , ordered_parameter_assignment }
| named_parameter_assignment { , named_parameter_assignment }
ordered_parameter_assignment ::= param_expression
Contrast this with an ordered list of port connections:
list_of_port_connections29 ::=
ordered_port_connection { , ordered_port_connection }
| named_port_connection { , named_port_connection }
ordered_port_connection ::= { attribute_instance } [ expression ]
The param_expression in not optional in a parameter list, but an expression is optional in a port connection list.

Related

get an element index in ocl collection ? [ocl_Eclipse]

i'm working on the following domain :
my domain diagram
i want to express the folowing constraint :
" a succession of two actions of Type Rotate is not allowed "
i tried this declaration but eclipse is not recognizing indexOf(element ) :
class Choreography
{
property actions : Action[+|1] { ordered composes };
attribute name : String[?];
/*Succession of two actions of Type is not permitted */
invariant rotate_succ:
self.actions->asSequence()->forAll(a1:Action,a2:Action
|
a1.oclIsTypeOf(Rotate) and (indexOf(a1)=indexOf(a2)+1) implies
not a2.oclIsTypeOf(Rotate)
)
;
Does anyone have an idea about how to work with the index of a random element from an ocl colletion ?
The
OrderedCollection(T):indexOf(obj : OclAny[?]) : Integer[1]
operation requires an OrderedCollection (Sequence/OrderedSet) as its source and an OclAny as its argument. You have not identified a source so OCL will consider first an implicit iterator leading to an
a1.indexOf(a1)
a2.indexOf(a1)
ambiguity which would be an error if an Action had an indexOf operation. Then it considers an implicit self which also fails since there is no Choreography.indexOf() operation.
I presume you meant
self.actions->indexOf(a1)
etc etc, or more readably put self.actions in a let-variable for multi-use.
(Use of oclIsTypeOf is very rarely right. Use oclIsKindOf unless you have a specific intent.)
(self.actions is already an OrderedCollection so there is no need for the asSequence()).
Your use of indexOf will lead to quadratic performance. Better to use indexes - something like:
let theActions = self.actions in
Sequence{1..theActions->size()-1}->forAll(index |
theActions->at(index).oclIsKindOf(Rotate)
implies not theActions->at(index+1).oclIsKindOf(Rotate))

FSharpLint, how to use the rule "InterfaceNamesMustBeginWithI" in SuppressMessageAttribute?

[<SuppressMessage("NameConventions","InterfaceNamesMustBeginWithI")>] //No effect
[<SuppressMessage("NameConventions","InterfaceNames")>] //It's working
module Test=
type [<AllowNullLiteral>] MutationEvent =
abstract attrChange: float with get, set
...
Also, failed to search source code about "InterfaceNamesMustBeginWithI".
The name of the rule is InterfaceNames, so you can suppress it thus:
[<SuppressMessage("","InterfaceNames")>]
module Test =
...
Also note that the first argument to SuppressMessage is not used by fsharplint, so it can be anything (although not null, strangely enough!)
There are pointers to InterfaceNamesMustBeginWithI in the documentation, but this is not correct.

Overloading operators for a class

Let's say I have the following class:
class A {
has $.val;
method Str { $!val ~ 'µ' }
}
# Is this the right way of doing it?
multi infix:<~>(A:D $lhs, A:D $rhs) {
('(', $lhs.val, ',', $rhs.val, ')', 'µ').join;
}
How would I overload an operator (e.g., +) for a class in the same manner as Str in the previous class?
I guess this only works for methods that are invoked on an instance object and using the multi operator-type:<OP>(T $lhs, T $rhs) { } syntax for operators is the right way to go about it but I'm unsure.
For instance, in Python there seems to be a correspondence between special methods named after the operators (e.g., operator.__add__) and the operators (e.g., +). Furthermore, any operator overloading for a custom class is done inside the class.
In Perl 6, operators are considered part of the current language. All things that relate to the current language are defined lexically (that is, my-scoped). Therefore, a multi sub is the correct thing to use.
If putting this code in a module, you would probably also want to mark the multi for the operator with is export:
multi infix:<~>(A:D $lhs, A:D $rhs) is export {
('(', $lhs.val, ',', $rhs.val, ')', 'µ').join;
}
So that it will be available to users who use or import the module (use is in fact defined in terms of import, and import imports symbols into the lexical scope).
While there are some operators that by default delegate to methods (for example, prefix:<+> calls Numeric), there's no 1:1 relation between the two, and for most operators their implementation is directly in the operator sub (or spread over many multi subs).
Further, the set of operators is open, so one is not restricted to overloading existing operators, but can also introduce new ones. This is encouraged when the new meaning for the operator is not clearly related to the normal semantics of the symbol used; for example, overloading + to do matrix addition would be sensible, but for something that couldn't possibly be considered a kind of addition, a new operator would be a better choice.
class A {
has $.val;
method Str { $!val ~ 'µ' }
}
multi infix:<~>(A:D $lhs, A:D $rhs) {
('(', $lhs.val, ',', $rhs.val, ')', 'µ').join;
}
dd A.new(val => "A") ~ A.new(val => "B"); # "(A,B)µ"
So yes, that is the correct way. If you want to override +, then the name of the sub to create is infix:<+>.
You can also provide the case for type objects by using the :U "type smiley", e.g.:
multi infix:<~>(A:U $lhs, A:U $rhs) {
'µ'
}
Hope this answers your question.

Ordering macro argument execution

I'm using a library for string interning (string-cache), that uses macros to efficient create elements (atom!). However for simplification here is a similar macro that demonstrates the problem
macro_rules! string_intern {
("d") => ("Found D");
}
say I need to call this macro from another macro and give it a string version of an identifier.
macro_rules! print_ident {
($id:ident) => (
string_intern!(stringify!($id));
);
}
However calling this macro
fn main() {
print_ident!(d);
}
Fails with error:
error: no rules expected the token `stringify`
--> <anon>:7:24
|
7 | string_intern!(stringify!($id));
| ^^^^^^^^^
Playground link
I know stringify! correctly converts to identifier d to string "d", because giving it to println! works as expected. Is there a way to pass the identifier I want turned into string to string_intern?
println! lets you do this because it uses format_args! under the covers, which is a compiler-provided "intrinsic" that forcibly evaluates its first argument before using it. You cannot do this from a user-defined macro; you'd have to write a compiler plugin (which requires a nightly compiler and no guarantee of stability).
So, yeah; you can't. Sorry. The only thing you can do is redefine the macro in such a way that you don't need an actual string literal, or change how you invoke it.
Your definition of string_intern! is expecting a literal "d" and nothing else, but you are passing in these tokens: stringify, !, ... which why it fails. The definition of string_intern! that you want is probably:
macro_rules! string_intern {
($e:expr) => {
match $e {
"d" => "Found D",
_ => "Not found",
}
}
}
which can accept any expression that evaluates to a string type.

initialize systemverilog (ovm) parameterized class array

I want to monitor several analysis ports, and "publish" the item through one analysis port.
It works for predefined item type, but fail to be parameterized.
The code:
class ovm_analysis_sink #(int NUM_PORTS = 1, type T = ovm_object ) extends ovm_component;
// .......................................
`ovm_component_param_utils(ovm_analysis_sink#(NUM_PORTS,T))
// .......................................
ovm_analysis_imp #(T,ovm_analysis_sink) mon_analysis_imp[NUM_PORTS-1:0];
ovm_analysis_port #(T) mon_analysis_port = new("mon_analysis_port", this);
virtual function void build() ;
string inst;
for(int i=0 ;i < NUM_PORTS ;i++ )
begin
$sformat(inst,"mon_analysis_imp_%0d",i);
mon_analysis_imp[i] = new(inst,this);
end
super.build() ;
endfunction : build
The usage of the analysis_sink:
ovm_analysis_sink #(3,a_type) a_item_sink;
And the error message:
Error-[ICTTFC] Incompatible complex type usage ovm_tb.sv, 42
Incompatible complex type usage in task or function call.
The following expression is incompatible with the formal parameter of the function.
The type of the actual is 'class $unit::ovm_analysis_sink#(3,class $unit::a_type)',
while the type of the formal is 'class $unit::ovm_analysis_sink#(1,class ovm_pkg::ovm_object)'.
Expression: this Source info: ovm_analysis_imp::new(inst, this)
The error says type incompatibility. That means the actual (run-time) and formal (compile-time) arguments/types of implementation port is not the same.
There is an error while declaration of analysis port. Declaring the port as shown above creates a handle of analysis imp port of type uvm_analysis_sink #(1,uvm_object) while, you want it to be of type uvm_analysis_sink #(3,a_type).
So, declare it as follows:
ovm_analysis_imp #(T,ovm_analysis_sink#(NUM_PORTS,T)) mon_analysis_imp[NUM_PORTS-1:0];
This shall remove the type conflict and make it type assignment compatible. Now any parameter overriding shall work.
I have created a sample UVM code on EDAPlayground for reference. Similar applies to your OVM testbench. For further information refer to this forum question.