Set parameterized virtual interface for array of agents - system-verilog

I am trying to create virtual interface with parameterized value for an array of agents.
interface trig_if #(parameter width=16) (input clk, input reset);
logic [width-1 :0] en;
logic [width-1 :0] trig_out;
endinterface
module tb_top;
..
..
trig_if #(.width(16)) trig1;
trig_if #(.width(8)) trig2;
trig_if #(.width(9)) trig3;
...
uvm_config_db#(virtual trig_if#(16))::set(null, "uvm_test_top.env.tagent[0].*", "trig_vif", trig1);
uvm_config_db#(virtual trig_if#(8))::set(null, "uvm_test_top.env.tagent[0].*", "trig_vif", trig2);
uvm_config_db#(virtual trig_if#(9))::set(null, "uvm_test_top.env.tagent[0].*", "trig_vif", trig3);
..
endmodule
//Env
class env extends uvm_env;
..
agent tagent[];//dynamic array
..
tagent = new[3];
..
for (int i=0; i < 3; i++) begin
tagent[i] = agent::type_id::create($sformatf("tagent[%0d]",i), this);
end
..
endclass
//driver
class driver extends uvm_driver;
virtual trig_if vif;
..
..
if(!uvm_config_db#(virtual trig_if)::get(this, "", "trig_vif", vif))
`uvm_fatal("NOVIF", {"Virtual interface must be set for: ", get_full_name(), ".vif"})
..
endclass
`
Error msg:
Virtual interface must be set for:uvm_test_top.env.tagent[1].driver
From this error, my understanding is the virtual interface created inside the driver getting 16 as width instead of the exact parameterized width which is 8.
How to pass the parameter value to agent/driver without parameterizing the agent/driver class?
Can anyone have idea on this please let me know.

Please try after modification as below:
module tb_top;
..
..
trig_if #(.width(16)) trig1;
trig_if #(.width(8)) trig2;
trig_if #(.width(9)) trig3;
...
uvm_config_db#(virtual trig_if#(16))::set(null, "uvm_test_top.env.tagent[0].*", "trig_vif_16b", trig1);
uvm_config_db#(virtual trig_if#(8))::set(null, "uvm_test_top.env.tagent[0].*", "trig_vif_8b", trig2);
uvm_config_db#(virtual trig_if#(9))::set(null, "uvm_test_top.env.tagent[0].*", "trig_vif_9b", trig3);
..
endmodule
Driver:
//driver
class driver extends uvm_driver;
virtual trig_if #(.width(16)) vif_16;
virtual trig_if #(.width(8)) vif_8;
virtual trig_if #(.width(9)) vif_9;
..
..
if(!uvm_config_db#(virtual trig_if#(16))::get(this, "", "trig_vif_16b", vif_16))
`uvm_fatal("NOVIF", {"Virtual interface must be set for: ", get_full_name(), ".vif16b"})
if(!uvm_config_db#(virtual trig_if#(8))::get(this, "", "trig_vif_8b", vif_8))
`uvm_fatal("NOVIF", {"Virtual interface must be set for: ", get_full_name(), ".vif8b"})
if(!uvm_config_db#(virtual trig_if#(9))::get(this, "", "trig_vif_9b", vif_9))
`uvm_fatal("NOVIF", {"Virtual interface must be set for: ", get_full_name(), ".vif9b"})
..
endclass

Related

Assignment operator type check failed on interface parameters

I'm working on parameterizing my interface to support multiple different instances:
compilation is failing on type mismatch:
assignment operator type check failed on instance hw_top (expecting
datatype compatible with 'virtual interface
foo_if#(.BASE_ADDR_1(32'h0000f480),.SIZE_1(32'h00000014),.BASE_ADDR_2(32'h00000000),.SIZE_2(32'h00000000))'
but found an incompatible
'foo_if#(.BASE_ADDR_1(32'h00002a00),.SIZE_1(32'h00000008),.BASE_ADDR_2(32'h00002a10),.SIZE_2(32'h00000008))
instance' instead).
This is how my interface is defined:
interface foo_if #(
parameter BASE_ADDR_1 = 'hf480,
parameter SIZE_1 = 'h14,
parameter BASE_ADDR_2 = 'h0,
parameter SIZE_2 = 'h0
)(
input clk,
input rst_n
);
//some logic
endinterface
This is how I instantiate it:
interface harness_if(
(
foo_if#(
.BASE_ADDR_1('h2a00),
.SIZE_1('h8),
.BASE_ADDR_2('h2a10),
.SIZE_2('h8)
) foo_if_i (
.clk (axi2af_clk),
.rst_n (resetn)
);
endinterface harness_if//
and I bind the harness if like this: harness_if
bind hw_top harness_if harness_i();
The whole idea of the parameter is that I can assign it to different values, so I'm unsure what is wrong.
The problem is that you are trying to place an instance of your interface where the port list of another interface should be. That is illegal syntax.
You want to place the interface instance inside the body of a module.
Here is a complete code example which shows 2 instances of your interface which use different parameter values:
interface foo_if #(
parameter BASE_ADDR_1 = 'hf480,
parameter SIZE_1 = 'h14,
parameter BASE_ADDR_2 = 'h0,
parameter SIZE_2 = 'h0
)(
input clk,
input rst_n
);
endinterface
module tb;
bit axi2af_clk, resetn;
foo_if # (
.BASE_ADDR_1('h2a00),
.SIZE_1 ('h8),
.BASE_ADDR_2('h2a10),
.SIZE_2 ('h8)
) foo_if_i (
.clk (axi2af_clk),
.rst_n (resetn)
);
foo_if # (
.BASE_ADDR_1('h1000),
.SIZE_1 (16),
.BASE_ADDR_2('h1010),
.SIZE_2 (16)
) foo_if_2 (
.clk (axi2af_clk),
.rst_n (resetn)
);
endmodule

Error fixing up map structure, incompatible struct bpf_elf_map used?

I am trying to learn ebpf map. Compiling the code with libbpf but getting the error like "Error fixing up map structure, incompatible struct bpf_elf_map used?". Here is my ebpf code:
#include <linux/bpf.h>
#include <linux/pkt_cls.h>
#include <stdint.h>
#include <iproute2/bpf_elf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#ifndef __section
# define __section(NAME) \
__attribute__((section(NAME), used))
#endif
#ifndef __inline
# define __inline \
inline __attribute__((always_inline))
#endif
struct bpf_map_def SEC("maps") port_h = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(int),
.value_size = sizeof(int),
.max_entries = 1,
};
static __always_inline int do_inline_hash_lookup(void *inner_map, int port)
{
int *result;
if (inner_map != &port_h)
return 99;
result = bpf_map_lookup_elem(&port_h, &port);
return result ? *result : 99;
}
__section("ingress")
int tc_ingress(struct __sk_buff *skb)
{
void *outer_map, *inner_map;
do_inline_hash_lookup(inner_map, 100);
return TC_ACT_OK;
}
__section("egress")
int tc_egress(struct __sk_buff *skb)
{
return TC_ACT_OK;
}
char LICENSE[] SEC("license") = "GPL";
Here is how I am loading the code into kernel:
tc filter del dev lo ingress
tc filter del dev lo egress
tc filter show dev lo ingress
# use right device like eth0 or lo
# Add qdisc to a particular interface like eth0 or lo
tc qdisc add dev lo clsact
# Load the object file into kernel
tc filter add dev lo ingress bpf da obj ./.output/map.bpf.o sec ingress
tc filter add dev lo egress bpf da obj ./.output/map.bpf.o sec egress
Any idea, what I am doing wrong? It will be a great help.
I think you need to declare your map according to the libbpf style:
#define __uint(name, val) int(*(name))[val]
#define __type(name, val) typeof(val) *(name)
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, int);
__type(value, int);
__uint(max_entries, 1);
} port_h __section(".maps");

How natural sorting a varchar column with Doctrine

I have a table with a column that contains names (varchar) but some names have numbers inside and the ordering is not the expected.
I have something like:
Courlis
D11 Espadon
D13 Balbuzard
D1 empacher
D2
But I expect:
Courlis
D1 empacher
D2
D11 Espadon
D13 Balbuzard
I've found lot of tips about it, but it's always on ordering numbers only stored as string: add a 0 to convert it in numbers, check the length of the string to place 1 before 10, etc... But in my case it can't work.
I can't use SQL query, because I use it in a form of a Symfony application that need a QueryBuilder.
Here is a way to do this with ICU collations in PostgreSQL (available from v10 on):
CREATE COLLATION en_natural (
LOCALE = 'en-US-u-kn-true',
PROVIDER = 'icu'
);
CREATE TABLE atable (textcol text COLLATE en_natural);
COPY atable FROM STDIN;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself, or an EOF signal.
>> Courlis
>> D11 Espadon
>> D13 Balbuzard
>> D1 empacher
>> D2
>> \.
test=# SELECT textcol FROM atable ORDER BY textcol;
textcol
---------------
Courlis
D1 empacher
D2
D11 Espadon
D13 Balbuzard
(5 rows)
Thanks to Laurentz Albe for your answer,for a Step by step in a Symfony application:
Create a Migration file that create the custom collation
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200221215657 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE COLLATION fr_natural (provider = "icu", locale = "fr-u-kn-true");');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('DROP COLLATION fr_natural');
}
}
Create a Doctrine Custom Function (Collate DQL)
<?php
namespace App\DQL;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
class Collate extends FunctionNode
{
public $expressionToCollate = null;
public $collation = null;
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->expressionToCollate = $parser->StringPrimary();
$parser->match(Lexer::T_COMMA);
$parser->match(Lexer::T_IDENTIFIER);
$lexer = $parser->getLexer();
$this->collation = $lexer->token['value'];
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return sprintf( '%s COLLATE %s', $sqlWalker->walkStringPrimary($this->expressionToCollate), $this->collation );
}
}
Register the new Function in the Doctrine config
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
server_version: '12'
orm:
auto_generate_proxy_classes: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
dql:
string_functions:
collate: App\DQL\Collate
And finally juste use it in the query when needed
$query = $this->createQueryBuilder('shell')
->orderBy('COLLATE(shell.name, fr_natural)', 'ASC')
->getQuery();
return $query->getResult();

How to use and compile standard c Lib in vala?

I'm just start few test in vala.
Vala is new for me . Sure I started to read a lot of tuto, but I don't understand my mistake.
how to use and compile the follow code?
using Gtk;
#include <stdio.h>
// compile with valac --pkg gtk+-3.0 hello_world_gtk_01.vala
public const int EXIT_SUCCESS=0;
int main (string[] args)
{
Gtk.init (ref args);
var window = new Window ();
window.title = "Hello, World!";
window.border_width = 10;
window.window_position = WindowPosition.CENTER;
window.set_default_size (350, 70);
window.destroy.connect (Gtk.main_quit);
stdout.printf ("Version de gtk: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION);
stdout.printf ("Version de gtk: %u.%u.%u\n", get_major_version() , get_minor_version(), get_micro_version());
string name, str;
name = "Version de gtk: ";
sprintf(str, "%d", get_major_version());
name = name+ str;
sprintf(str, "%d", get_minor_version());
name = name+ str;
sprintf(str, "%d", get_micro_version());
name = name+ str+ "\n";
var label = new Label (name);
window.add (label);
window.show_all ();
Gtk.main ();
return EXIT_SUCCESS;
}
What is bad ?
Gcc said
hello_world_gtk_01.vala:2.2-2.9: error: syntax error, invalid preprocessing directive
#include <stdio.h>
^^^^^^^^
hello_world_gtk_01.vala:2.10-2.10: error: syntax error, expected identifier
#include <stdio.h>
^
Compilation failed: 2 error(s), 0 warning(s)
could you help me to understand how to manage stdio?
Vala generates C code, but you can't pass C straight from the Vala file to the generated C. The Vala [CCode] attribute gives fine control over the generated C, but you won't need that in most cases. For an example of standard C names and their GLib equivalents take a look at the glib-2.0.vapi file in the Vala repository. Other standard C and POSIX extensions are in posix.vapi. There is also an in depth tutorial on writing a binding from Vala to a C library. Writing a binding, however, is a more advanced topic and what you are trying to achieve in your example doesn't need a new binding.
Your example uses string interpolation. In Vala a data type can have a method, so one way to write what you want would be:
name = "Version de gtk: %u.%u.%u\n".printf( get_major_version (), get_minor_version (), get_micro_version ());
Vala also has a string template syntax, #"", and and then an expression, $(), inside the string is evaluated. For example:
name = #"Version de gtk: $(get_major_version ()).$(get_minor_version ()).$(get_micro_version ())\n";
This works because uint, the return value of the function calls, has a to_string () method that is implicitly called by the string template.
Here's your example modified to use the string template method:
using Gtk;
// compile with valac --pkg gtk+-3.0 hello_world_gtk_01.vala
public const int EXIT_SUCCESS=0;
int main (string[] args)
{
Gtk.init (ref args);
var window = new Window ();
window.title = "Hello, World!";
window.border_width = 10;
window.window_position = WindowPosition.CENTER;
window.set_default_size (350, 70);
window.destroy.connect (Gtk.main_quit);
stdout.printf ("Version de gtk: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION);
stdout.printf ("Version de gtk: %u.%u.%u\n", get_major_version() , get_minor_version(), get_micro_version());
var name = #"Version de gtk: $(get_major_version ()).$(get_minor_version ()).$(get_micro_version ())\n";
var label = new Label (name);
window.add (label);
window.show_all ();
Gtk.main ();
return EXIT_SUCCESS;
}

CanCan singleton loading with pluralized class name

I'm currently experiencing an issue with the latest version of CanCan. It seems that the gem won't load singleton resources with pluralized names.
class Preferences < ActiveRecord::Base
self.table_name = 'preferences'
belongs_to :user
end
class User < ActiveRecord::Base
has_one :preferences
end
#controller
class PreferencesController < ApplicationController
before_filter :authenticate_user! #from Devise
load_and_authorize_resource :singleton => true,
:through => :current_user,
:through_association => :preferences,
:parent => false
end
#ability.rb
class Ability
include CanCan::Ability
def initialize(user)
can [:read, :update], Preferences, :user_id => user.id
end
end
I keep getting an error like this when I run my controller spec:
Failures:
1) PreferencesController GET #show should return http success
Failure/Error: get :show
NameError:
uninitialized constant Preference
# ./spec/controllers/preferences_controller_spec.rb:10:in `block (3 levels) in <top (required)>'
It seems no matter what combination of load_resource arguments I try, I can't get my specs to pass again without reverting back to loading the resource manually like this:
class PreferencesController < ApplicationController
before_filter :authenticate_user!
def show
#preferences = current_user.preferences
authorize! :read, #preferences
end
end
Is there some magic combination of load_and_authorize_resource parameters I need to use? I have this same configuration working in another singleton controller where the resource falls under normal Rails conventions (i.e. User has_one :profile), so I know this works already under normal situations.