Skip to content
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

Merged
merged 40 commits into from
Mar 22, 2018
Merged

Wishbone BFM #312

merged 40 commits into from
Mar 22, 2018

Conversation

slaweksiluk
Copy link
Contributor

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.

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
But need to fix memory write read values (currently
checking is disabled in tb). Also need to perfrom
block write and read back to back
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.
Copy link
Collaborator

@kraigher kraigher left a 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/.
--
Copy link
Collaborator

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.

Copy link
Contributor Author

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;
Copy link
Collaborator

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;
Copy link
Collaborator

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);
Copy link
Collaborator

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.

Copy link
Contributor Author

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?

Copy link
Collaborator

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
Copy link
Collaborator

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/.
--
Copy link
Collaborator

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);
Copy link
Collaborator

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/.
--
Copy link
Collaborator

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);
Copy link
Collaborator

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;
Copy link
Collaborator

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.

Copy link
Contributor Author

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.

Copy link
Collaborator

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.

Copy link
Collaborator

@kraigher kraigher Mar 3, 2018

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);
Copy link
Collaborator

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);
Copy link
Collaborator

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.

@slaweksiluk
Copy link
Contributor Author

slaweksiluk commented Mar 6, 2018

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.

@kraigher
Copy link
Collaborator

kraigher commented Mar 6, 2018

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
Copy link
Collaborator

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;
Copy link
Collaborator

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.

Copy link
Contributor Author

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.

@slaweksiluk
Copy link
Contributor Author

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.

@kraigher
Copy link
Collaborator

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 pytest vunit/test/lint/test_pep8.py.
First you need to install pytest and pep8 using pip install pytest pep8

@kraigher
Copy link
Collaborator

@slaweksiluk Do you need any help finishing this up?

@slaweksiluk
Copy link
Contributor Author

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.

@kraigher
Copy link
Collaborator

We write in the documentation that the entire verification component library is in beta so maybe the maturity of wishbone needs no additional disclaimer.

@kraigher kraigher merged commit f7542ea into VUnit:master Mar 22, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants