Can I use wires from top module as inputs in a bind module instantiation? (SystemVerilog) - system-verilog

I have a simple module PRINTER that I want to instantiate with bind to another module BIG_DUT in one testbench BIG_TB. BIG_DUT has an instance of another module SMALL_DUT, which has most stuff that I want to use in PRINTER. I have another testbench SMALL_TB which has an instance of SMALL_DUT as well as an instance of PRINTER, and in this testbench I would like to bind the PRINTER to the SMALL_DUT.
In my PRINTER module I need a wire that is present in either testbench, as well as in BIG_DUT, but not in SMALL_DUT. Is there any way to use the wire from the testbench instead of trying to access the wire inside of BIG_DUT/SMALL_DUT, while still having easy access to other wires/stuff in SMALL_DUT?
Example code:
module SMALL_DUT();
// Stuff I want to use in the PRINTER
...
endmodule
module BIG_DUT(
input wire big_dut_input
);
SMALL_DUT small_dut_in_big();
endmodule
module PRINTER(
// Can I take input here from tb?
);
// For BIG_TB, I could use big_dut_input and small_dut_in_big.stuff_i_want_to_use
// For SMALL_TB, there is no wire I could use, but I can reference stuff_i_want_to_use
endmodule
module BIG_TB();
wire my_tb_wire_big; // Want to use this in PRINTER, also present in BIG_DUT
BIG_DUT big_dut(
.big_dut_input(my_tb_wire_big)
);
// I could potentially do
// bind big_dut.small_dut_in_big
// here to get the same access pattern to stuff inside PRINTER
bind big_dut
PRINTER big_printer(
// Could I input my_tb_wire_big here?
);
endmodule
module SMALL_TB();
wire my_tb_wire_small; // Same usage as my_tb_wire_big in PRINTER
...
SMALL_DUT small_dut();
bind small_dut
PRINTER small_printer(
// Could I input my_tb_wire_small here?
);
endmodule
(In this simple example I could of course add another input to SMALL_DUT, but that is used in my real code, and I don't want the extra input there.)

You can always put a hierarchical reference in an instance port connection. This is true regardless of using the bind construct or not.
module SMALL_DUT();
bit stuff;
...
endmodule
module BIG_DUT(
input wire big_dut_input
);
SMALL_DUT small_dut_in_big();
endmodule
module PRINTER(
input signal1, signal2, signal3)
// stuff
endmodule
module BIG_TB();
wire my_tb_wire_big; // Want to use this in PRINTER, also present in BIG_DUT
BIG_DUT big_dut(
.big_dut_input(my_tb_wire_big)
);
bind big_dut
PRINTER big_printer(
BIG_TB.my_tb_wire_big, small_dut_in_big.stuff);
);
endmodule
module SMALL_TB();
wire my_tb_wire_small; // Same usage as my_tb_wire_big in PRINTER
...
SMALL_DUT small_dut();
bind small_dut
PRINTER small_printer(
SMALL_TB.my_tb_wire_small, stuff
);
endmodule

Related

How to get the read signals in the sequence from driver in pipeline style UVM?

I'm trying to get read data (HRDATA) from a driver in the sequence or test.
This is my driver:
////////// Pipelined UVM Driver //////////
class ahb_pipelined_driver extends uvm_driver #(ahb_seq_item);
`uvm_component_utils(ahb_pipelined_driver)
/// Virtual Interface
virtual ahb_interface ahb_if;
/// Constructor
....
function void build_phase(uvm_phase phase);
super.build_phase(phase);
...
endfunction
forever begin
ahb_if.HADDR <= req.HADDR;
ahb_if.HWRITE <= req.HWRITE;
ahb_if.HBURST <= req.HBURST;
req.HRDATA = ahb_if.HRDATA;
req.HRESP = ahb_if.HRESP;
ahb_if.HWDATA <= req.HWDATA;
end
// Return the Request as Response
seq_item_port.put(req);
end_tr(req);
end
endtask:
endclass:
I read the read data from req.HRDATA = ahb_if.HRDATA; in the driver, and I can check the value.
But, the problem is that I'd like to send read data to the sequence but this sequence immediately finished after I call seq_item_port.get() in the driver. So I can’t both wait for the read data to be available and have pipelined operation.
I want to send the read data to the sequence or test from the driver. How am I supposed to do that?
You are not following the recommended UVM approach.
The driver should not sample the "read" data and check it. You should create a UVM agent with a driver and a monitor. The monitor should sample the read data and send it to a scoreboard for checking.
I recommend that you change your driver such that it no longer tries to sample the read data. Then create a UVM monitor which collects all AHB transactions (reads and writes) and sends them to a scoreboard.
See also:
Basic UVM example
UVM AHB example on EDA Playground

Sharing maps between same eBPF programs loaded onto different interfaces with libbpf

I want to load the same eBPF program for XDP hook onto different interfaces of a switch and all the programs should share the same map. I have gone through the post (exactly my target) post 1 and post 2. However, I could not get things up and running.
I know that I need to use bpf_map__reuse_fd(), but how exactly do I use it without creating the maps first? Also, individual programs in the interfaces will create their own maps, isn't it so?
In comments of post 2, following the steps we first create structs for both prog1 and prog2, then load prog1, get the map fds to use in prog2. But, in this case, how will the maps be created without loading the BPF program and then shared?
I have only two programs - one kernel space BPF program and one user space program that loads the code. Here are my code snippets.
In file xxx_kern.c
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u32);
__type(value, __u32);
__uint(max_entries, 10);
} xdp_map_t SEC(".maps");
In file xxx_user.c
int main()
{
struct bpf_object *obj = NULL;
obj = bpf_object__open("xxx_kern.o");
struct bpf_map *map1 = bpf_object__find_map_by_name(obj, "xdp_map_t ");
int map1_fd = bpf_object__find_map_fd_by_name(obj, "xdp_map_t ");
bpf_map__reuse_fd(map1, map1_fd);
// load and attach the program with xdp_program__attach()
// verifythe fd value of map ```xdp_map_t``` from different interfaces
printf("\nMap1_fd value: %d\n", map1_fd);
}
Can someone tell the proper steps in this scenario?
Note that I am using libbpf.
My suggest is to follow these tutorial enter link description here. It pins the map in a bpffs, a virtual file system that permit to access the map and the bpf structures every time you want. Keep your definition of the map and do not use the bpf_map_def cause it's deprecated.

I2C: Raspberry Pi (Master) read Arduino (Slave)

I would like to read a block of data from my Arduino Mega (and also from an Arduino Micro in another project) with my Raspberry Pi via I2C. The code has to be in Perl because it's sort of a plug-in for my Home-Automation-Server.
I'm using the Device::SMBus interface and the connection works, I'm able to write and read single Bytes. I can even use writeBlockData with register address 0x00. I randomly discovererd that this address works.
But when I want to readBlockData, no register-address seems to work.
Does anyone know the correct register-address, or is that not even the problem that causes errors?
Thanks in advance
First off, which register(s) are you wanting to read? Here's an example using my RPi::I2C software (it should be exceptionally similar with the distribution you're using), along with a sketch that has a bunch of pseudo-registers configured for reading/writing.
First, the Perl code. It reads two bytes (the output of an analogRead() of pin A0 which is set up as register 80), then bit-shifts the two bytes into a 16-bit integer to get the full 0-1023 value of the pin:
use warnings;
use strict;
use RPi::I2C;
my $arduino_addr = 0x04;
my $arduino = RPi::I2C->new($arduino_addr);
my #bytes = $arduino->read_block(2, 80);
my $a0_value = ($bytes[0] << 8) | $bytes[1];
print "$a0_value\n";
Here's a full-blown Arduino sketch you can review that sets up a half dozen or so pseudo-registers, and when each register is specified, the Arduino writes or reads the appropriate data. If no register is specified, it operates on 0x00 register.
The I2C on the Arduino always does an onReceive() call before it does the onRequest() (when using Wire), so I set up a global variable reg to hold the register value, which I populate in the onReceive() interrupt, which is then used in the onRequest() call to send you the data at the pseudo-register you've specified.
The sketch itself doesn't really do anything useful, I just presented it as an example. It's actually part of my automated unit test platform for my RPi::WiringPi distribution.

Can't implicitly connect port on instance error

I'm new to systemverilog and I'm having this error that I can't seem to figure out. This is the error message:
Error (10897): SystemVerilog error at TopLevel.sv(103): can't
implicitly connect port "ALU_SRC_B" on instance "control_module" of
module "Control" - no such object is visible in the present scope
This is the piece of code that's failing:
// Control module
Control control_module (
.Instruction(Instruction[8:5]),
.ALU_OP,
.ALU_SRC_B,
.REG_WRITE,
.BRANCH,
.MEM_WRITE,
.MEM_READ,
.REG_DST,
.MEM_TO_REG,
.HALT(HALT)
);
And this is my Control Module:
module Control(
input [8:0] Instruction,
output logic [3:0] ALU_OP,
output logic [1:0] ALU_SRC_B,
output logic REG_WRITE,
output logic BRANCH,
output logic MEM_WRITE,
output logic MEM_READ,
output logic REG_DST,
output logic MEM_TO_REG,
output logic HALT
);
logic [3:0] OPCODE = Instruction[8:5];
always_comb begin
...
The Control Module is in the correct directory so why am I getting this error?
I gave your code a try and the reason you get the message is that for your unconnected ports in control_module, you need to show empty brackets to indicate this is unconnected. Otherwise, you get the message as shown (which is a little cryptic).
TESTBENCH:
module tb;
wire[8:0] Instruction;
wire HALT;
// Control module
Control control_module (
.Instruction(Instruction[8:5]),
.ALU_OP(),
.ALU_SRC_B(),
.REG_WRITE(),
.BRANCH(),
.MEM_WRITE(),
.MEM_READ(),
.REG_DST(),
.MEM_TO_REG(),
.HALT(HALT)
);
initial begin
#100ns
$finish;
end
endmodule
DESIGN:
// Code your design here
module Control(
input [8:0] Instruction,
output logic [3:0] ALU_OP,
output logic [1:0] ALU_SRC_B,
output logic REG_WRITE,
output logic BRANCH,
output logic MEM_WRITE,
output logic MEM_READ,
output logic REG_DST,
output logic MEM_TO_REG,
output logic HALT
);
endmodule
You can find a working example here: https://www.edaplayground.com/x/63Eq
Try taking out one of the empty brackets and notice you get the same error message..

System call implementation in Pintos

I want to implement the already defined system calls in PintOS ( halt(), create()...etc defined in pintos/src/lib/user/syscall.c ). The current system call handler in pintos/src/userprog/syscall.c does not do anything. How do I make a process that makes system calls. Further I need to myself add a few system calls. How do I proceed in that too. But first I need to implement the existing system calls.
The default implementation in pintos terminates the calling process.
goto this link.There is explanation on where to modify the code to implement the system calls.
The "src/examples" directory contains a few sample user programs.
The "Makefile" in this directory compiles the provided examples, and you can edit it compile your own programs as well.
This program/process when run will inturn make a system call.
Use gdb to follow the execution of one such program a simple printf statement will eventually call write system call to STDOUT file.
The link given also has pointers on how to run pintos on gdb, my guess is you are using either bochs or qemu.In any case just run the gdb once with a simple hello world program running on pintos.
This will give u an idea of how the system call is made.
static void
syscall_handler (struct intr_frame *f)// UNUSED)
{
int *p=f->esp;
switch(*p)
case *p=SYS_CREATE // NUMBER # DEFINED
const char *name=*(p+1); //extract the filename
if(name==NULL||*name==NULL)
exit(-1);
off_t size=(int32_t)*(p+2);//extract file size
f->eax=filesys_create(name,size,_FILE); //call filesys_create
//eax will have the return value
}
This is pseudo code for sys_create .. all file system related system call are very trivial,
Filesys realted system calls like open read write close needs you to translate file to their corresponding fd (file descriptor). You need to add a file table for each process to keep track this, this can either be preprocess data or a global data.(UR choice),
case (*p==SYS_WRITE)
{
// printf("wite syscall\n");
char *buffer=*(p+2);
unsigned size=*(p+3);
int fd=*(p+1);
// getiing the fd of specified file
struct file *fil= thread_current()->fdtable[fd];/ my per thread fdtable
if(fd==1) goto here;
if(is_directory(fil->inode)){
exit(-1);
goto done;
}
here:
if(buffer>=PHYS_BASE)exit(-1);
if(fd<0||fd>=128){exit(-1);}
if(fd==0){exit(-1);} // writing to STDIN
if(fd==1) //writing to STDOUT
{
int a=(int)size;
while(a>=100)
{
putbuf(buffer,100);
buffer=buffer+100;
a-=100;
}
putbuf(buffer,a);
f->eax=(int)size;
}
else
if(thread_current()->fdtable[fd]==NULL)
{f->eax=-1;}
else
{
f->eax=file_write(thread_current()->fdtable[fd],buffer,(off_t)size);
}
done: ;
}//printf("write");} /* Write to a file. */
Open - adds anew entry to fdtable and return the fd number u give to the file,
close - remove that entry from fd table
read - similar to write.
The process_create ,wait are not simple to implement...
Cheers :)