-
Notifications
You must be signed in to change notification settings - Fork 263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wishbone BFM #312
Wishbone BFM #312
Conversation
Conflicts: vunit/vhdl/verification_components/src/wishbone_master.vhd vunit/vhdl/verification_components/test/tb_wishbone_master.vhd
Conflicts: vunit/vhdl/verification_components/test/tb_wishbone_master.gtkw
One wb test failed
Delay needed between write and read
Use Vunit message passing tracing instead
It is in wishbone slave module in ack process when the third (last?) msg is processed.
Call receive is not valid for such a use case (multi process BFM)
To remove the need for delays in tb. Not yes simulated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have reviewed the code an written down my suggestions. Let me know if you need any help. The big issues are:
- Copyright
- Wishbone slave needs to get the memory_t instance from the outside to be usable.
-- This Source Code Form is subject to the terms of the Mozilla Public | ||
-- License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
-- You can obtain one at http://mozilla.org/MPL/2.0/. | ||
-- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright notice needs to give copyright to Lars Asplund like all other copyright notices.
It is fine if you mention your name to give you credit for the the work but copyright needs to be given to Lars for this to be merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, no problem I will leave Copyright as in other vunit sources. I will also add line:
-- Author: Slawomir Siluk slaweksiluk@gazeta.pl
library ieee; | ||
use ieee.std_logic_1164.all; | ||
|
||
--use work.axi_pkg.all; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dead code
--use work.axi_pkg.all; | ||
use work.queue_pkg.all; | ||
use work.bus_master_pkg.all; | ||
--use work.axi_private_pkg.all; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dead code
variable status : com_status_t; | ||
begin | ||
-- Cannot use receive, as it deletes the message | ||
--receive(net, bus_handle.p_actor, request_msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use receive if you set request_msg := null_message before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean:
request_msg := null_message
receive(net, bus_handle.p_actor, request_msg)
I sholud still manually delete the message, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The receive procedure will delete the request_msg if it is not already null_message.
By setting it to null_message before you inhibit receive from deleting the message.
You take the responsibility to delete the message yourself when you are done using it.
Ideally you should set the request_msg to null_message right after you push it to a queue since that is the point where ownership is semantically handed over to the queue. The process that pops the queue takes ownership and should delete it once it is done with it.
end loop; | ||
end process; | ||
|
||
acknowladge : process |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
misspelled acknowledge
-- This Source Code Form is subject to the terms of the Mozilla Public | ||
-- License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
-- You can obtain one at http://mozilla.org/MPL/2.0/. | ||
-- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright needs to be given to Lars. You can keep your name for crediting the contribution.
show(tb_logger, display_handler, verbose); | ||
show(default_logger, display_handler, verbose); | ||
show(master_logger, display_handler, verbose); | ||
show(com_logger, display_handler, verbose); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All these calls (except test_runnner_watchdog) should be after test_runner_setup in a process. I do not recommend making these calls as concurrent statements.
-- This Source Code Form is subject to the terms of the Mozilla Public | ||
-- License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
-- You can obtain one at http://mozilla.org/MPL/2.0/. | ||
-- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright needs to be given to Lars, you can keep your names for crediting the work but have to give up copyright.
set_format(display_handler, verbose, true); | ||
show(tb_logger, display_handler, verbose); | ||
show(default_logger, display_handler, verbose); | ||
show(com_logger, display_handler, verbose); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These calls (except test_runner_watchdog) should not be concurrent and should be located after test_runner_setup
variable msg_type : msg_type_t; | ||
variable data : std_logic_vector(dat_i'range); | ||
variable addr : natural; | ||
variable memory : memory_t := new_memory; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using a memory_t from a VC you should convert it by using to_vc_interface. This enables permission checks on all read/write accesses which is not enabled by default as the test_bench should read and write freely but the VC should respect the permission settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to pass memory as entity generic. Should I still use to_vc_interface in that case? I will look for some examples in existing vunit VC's.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to_vc_interface should be used privately within the VC to create a new memory object which is identical to the one that was passed into the VC by the user. This has the effect of enabling read/write permission for all read/write operations to the memory when using the new value returned by to_vc_interface. This is to make it easier to support the two use cases of reading/writing memory from the test bench without permission checks and having axi_slave etc. perform memory operations with permission checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also ideally you should create a wishbone_slave_t
record type that is created with a new_wishbone_slave
function like axi_slave. The new_wishbone_slave
can take a memory_t
as an argument and maybe also a logger_t.
Internally in new_wishbone_slave
an actor_t
can be created that allows you to define command functions to the wishbone slave such as enable_random_stall(net : net_t, slave : wishbone_slave_t)
or set_random_stall_probability(net : net_t, slave : wishbone_slave_t, probability : real);
get_message(net, bus_handle.p_actor, request_msg); | ||
msg_type := message_type(request_msg); | ||
if msg_type = bus_read_msg then | ||
push(rd_request_queue, request_msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set request_msg to null_message after push since ownership was transferred into the queue.
if msg_type = bus_read_msg then | ||
push(rd_request_queue, request_msg); | ||
elsif msg_type = bus_write_msg then | ||
push(wr_request_queue, request_msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set request_msg to null_message after push since ownership was transferred into the queue.
Memory is now external to slave
To not to prevent from multi master instances.
Ok, thank you for comments. I applied most of them, excluding random parameters set via msg. It is definitely better solution, however I need to have some deeper look at axi slaves to implement it. |
Regarding setting random parameters via message. The first you could to is just add them as fields in the wishbone_slave_t record and then rename them to initial_rand_stall_probability. That way it is forward compatible to a future where the rand_stall_probability can be set at run-time as well. In the axi_slaves we wrap all generics in the axi_slave_t record. |
generic ( | ||
wishbone_slave : wishbone_slave_t; | ||
max_ack_dly : natural := 0; | ||
rand_stall : boolean := false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename max_ack_dly and rand_stall to initial_max_ack_delay and initial_rand_stall_probability : real and move them into wishbone_slave_t to make it forward compatible with changing them at runtime and more similar to axi_slave_t.
package body wishbone_pkg is | ||
|
||
impure function new_wishbone_slave( | ||
memory : memory_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add max_ack_delay and random_stall_probability parameters here and to wishbone_slave_t to make it similar to axi_slave_t and forward compatible with setting them at run-time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will go that way. I will also change both parameters to be probability of having value 1, E.g:
init_stall_high_probability : real := 0.0;
init_ack_high_probability : real := 1.0;
It seems better defined this way. I also consider adding random stb signal stimulation option to master VC.
I changed both parameters to be probability 0.0 to 1.0 range. Also I moved them to wishbone_slave_t record. Still need to add support for runtime probability changes. |
Great work. I am ready to accept this pull request. You just need to fix the broken checks found by Travis CI: https://travis-ci.org/VUnit/vunit/jobs/352852061 I think the only problem is the Python PEP8 code style checks that are broken by the changes in the verification_components run.py file. You can run this check locally using |
@slaweksiluk Do you need any help finishing this up? |
I fixed coding style errors. I was using designed bfm's in my project to verify it in real conditions. Wishbone slave looks good, but I haven't got time to try wishbone master. Moreover I remember I saw small bug in wishbone master regarding cyc signal one clock cycle late termination. However it only occurs at the end of block cycle, so it is not harmful. I will create issues for it when I trace it. I think you should mentioned somewhere in documentation that wishbone bfms are still in testing. |
We write in the documentation that the entire verification component library is in beta so maybe the maturity of wishbone needs no additional disclaimer. |
I think my implementations of Wishbone Slave and Master Bus Functional Models are ready to be reviewed. Currently only pipelined mode is supported. Read/Write cycles lengths can be 1 (Single Read/Write) or more (Block Read/Write).
Wishbone Slave BFM
It is wrapper for Vunit memory VC. Currently memory is internal variable, but it should rather be passed as generic parameter. Manual tb with generic test cases is provided.
Wishbone Master BFM
Receives bus write and bus read messages from main sequencer. Consecutive groups of bus write/reads messages are merged into block cycles. Cycle is finished when next message is the opposite action (e.g write command after read) or there is no more messages in actor inbox. Test bench with Master and Slave connected is provided.
I didn't want to add new calls to bus_maser_pkg. However adding calls like: bus_write_block and bus_read_block might be good idea.