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

[rom_ctrl, dv] Exclusions for tlul_adapter_sram and prim_fifo_sync #25869

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

KinzaQamar
Copy link
Contributor

No description provided.

@KinzaQamar KinzaQamar force-pushed the rom_ctrl_excl branch 3 times, most recently from 71c7e85 to 6338c63 Compare January 15, 2025 14:14
Comment on lines 149 to 162
// The case 1101 is non-occuring for the conditional statement below.
//
// One reason is that the depth of the fifos is 2. When we write something in the fifo, we read the
// same thing on the next cycle and update the wptr and rptr respectively. It can happen if we
// delay reads and make them happen after writing to both of the location of the fifos. This will
// lead to increment only wptr. But this can't happen for u_sramreqfifo because when we write into
// the fifo we will get rvalid_o in u_sramreqfifo which depends on empty and under_rst. For not
// having sramreqfifo_rready when we write to the fifo is not possible as it depends on
// reqfifo_rvalid and we can't hope for not having a reqfifo_rvalid if there was a request to
// write something in u_sramreqfifo on the last cycle.
CHECKSUM: "1909897872 4057018282"
INSTANCE: tb.dut.u_tl_adapter_rom
Condition 35 "3680494467" "((gnt_i | missed_err_gnt_q) & reqfifo_wready & sramreqfifo_wready
& sramreqaddrfifo_wready) 1 -1" (3 "1101")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just had a look at this item and I think it's impossible for any instance of the adapter, because the two wready signals can never be different from one another. Because of this, I've actually just opened #25905.

I think I agree that sramreqfifo_wready will never be false at all (for the reason you give). As such, we'll probably need a tweaked version of this because there will be a conditional coverage hole for "110".

But I think we can also shorten the description a bit. Maybe something like this?

// The case 1101 is cannot happen for the conditional statement below.
//
// This is because sramreqfifo_wready can never be false. The u_sramreqfifo FIFO has depth 2 and
// will contain have more than one item. The ROM always responds in exactly one cycle, so
// sramreqfifo_rready will always be true if the FIFO is nonempty and a second item can never be
// added without removing the current one.

Comment on lines +164 to +160
// The case 011 for the conditional statements below is non-occuring.
//
// When rvalid_o=0, the fifo is empty and it is seen as reqfifo_rvalid in tlul_adapter_sram.sv.
// rready_i comes in as input from tlul_adapter_sram. If rready_i=1, it means d_valid is true which
// goes to u_sram_byte as one of the port of tl_o_int and d_ready port of tl_i_int is true which
// comes out from u_sram_byte. But d_valid to be true requires reqfifo_rvalid true.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to think a bit to convince myself of why this was true and I think it can be reworded a bit to make it clearer?

    // This item is impossible because it is rready_i -> rready_o for a u_reqfifo instance in any
    // tlul_adapter_sram. This is because rready_i is driven by reqfifo_rready, which is d_ack. This
    // is only true when tl_o_int.d_valid is true, which means the ROM is responding to a request.
    // That request will have been pushed into u_reqfifo as it was sent out, so the FIFO is not
    // empty and rready_o must be true.

Does the reasoning sound right to you?

@rswarbrick
Copy link
Contributor

As a general comment, I'd probably suggest harvesting these items from the PR in groups of one or two and making PRs for the groups. That way, they needn't all be dependent one one another.

We can always do the "commit merging" as part of landing the individual PRs. This is a pretty trivial file format, so it's not difficult :-)

Comment on lines +173 to +172
// For u_rspfifo, Pass=1 and rvalid_o is ~(fifo_empty & ~wvalid_i) & ~under_rst. wvalid_i comes
// from u_tl_adapter_rom as rspfifo_wvalid. rspfifo_wvalid needs both rvalid_i (response from rom)
// and reqfifo_rvalid. If we want rready_i=1, we want reqfifo_rready=1 in u_tl_adapter_rom.
// reqfifo_rready further gets assigned by tl_o_int.dvalid and tl_i_int.d_ready. For
// tl_o_int.dvalid to set itself true requires reqfifo_rvalid. Which means that read from reqfifo
// is happening and u_rspfifo needs to respond to that read on the same cycle. So, we will get
// rvalid_o with rready_i.
INSTANCE: tb.dut.u_tl_adapter_rom.u_rspfifo
Condition 3 "1324655787" "(rvalid_o & rready_i & ((~gen_normal_fifo.under_rst))) 1 -1" (1 "011")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is correct, but the logic took me a bit of time to follow. Reasoning through it myself, I ended up with this, which I think might be slightly easier to follow?

// The following item cannot happen. It requires that rvalid_o = 0 and rready_i = 1 in u_rspfifo.
//
// If rready_i is true in u_rspfifo, that means that rspfifo_rready is true in the SRAM adapter.
// This means that reqfifo_rdata.op = OpRead, that reqfifo_rdata.error is false, and that
// reqfifo_rready is true. The latter signal is d_ack, which can only be true if tl_o_int.d_valid is
// true, which implies that the d_valid signal is true. Since we know that the operation is OpRead
// and it doesn't have an error, the combinatorial logic that calculates d_valid yields
// rspfifo_rvalid. That signal is the rvalid_o output port from u_rspfifo. As a result, if rready_i
// is true in u_rspfifo then rvalid_o must also be true.

Comment on lines +189 to +197
// The case 110 for the conditional statements below is non-occuring.
//
// To cover 110, all the bits of the conditional statements should be true. If under_rst is true,
// then we get empty_o in u_fifo_cnt is true. empty_o=1 when wptr_wrap_cnt_o = rptr_wrapt_cnt_o in
// u_fifo_cnt. As Secure is true in case of rom_ctrl, wptr_wrap_cnt_o and rptr_wrap_cnt_o comes out
// as cnt_o from u_wptr and u_rptr respectively. Both u_wptr and u_rptr are instances of same
// module (prim_count). Then cnt_o gets assigned by cnt_q[0] which is updated as a result of
// fpv_force[0] + cnt_unforced_q. fpv_force is wired to 0 as rom_ctrl doesn't define the macro
// PrimCountFPV. cnt_unforced_q comes out as q_o from u_cnt_flop. In u_cnt_flop, q_o comes out from
// u_impl_generic instance which contains non-blocking assignments to q_o. If !rst_ni, then q_o
// will get assigned by a ResetValue which is 0 in this case. Otherwise, q_o will be delayed by
// d_i. This will get cnt_q=0 in both u_ptr and w_ptr which leads to cnt_o=0. When cnt_o in both
// w_ptr and r_ptr is 0 leads wptr_wrap_cnt_q and rptr_wrap_cnt_q to be equal. Which means the
// empty_o=1 in u_fifo_cnt and it will be seen as fifo_empty in u_**fifo.
//
// For u_reqfifo, Pass=0 so fifo_empty is rvalid_o. Hence, we can't see rvalid_o when under_rst is
// true. With no rvalid_o, we can't get rready_i and the reasoning above for case 011 for the same
// conditional statement explains why.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a rather shorter chain of logic that gets here:

// We can never see rvalid_o && under_rst in u_reqfifo in any tlul_adapter_sram instance. Since the
// Pass parameter is false for u_reqfifo, rvalid_o is only true if the FIFO is nonempty. Since the
// FIFO clears on reset, this cannot be true in the first cycle after reset. But that is the only
// cycle when under_rst is true.

Comment on lines +210 to +211
// For u_rspfifo, Pass=1 and rvalid_o is (fifo_empty & ~wvalid_i) & ~under_rst. wvalid_i comes from
// u_tl_adapter_rom as rspfifo_wvalid. rspfifo_wvalid needs both rvalid_i (response from rom) and
// reqfifo_rvalid. But as explained above that we can't get rvalid_o when under_rst=1. This gets
// the (fifo_empty & ~wvalid_i) term true which means empty=1. Since to cover 110, we need
// under_rst=1 which then negates to 0 inside the assignment leads to no rvalid_o. So, same
// conclusion as u_reqfifo that we can't get rvalid_o when under_rst=1.
//
// For rready_i, it comes in as rspfifo_rready from u_tl_adapter_rom through a conditional
// assignment. If the condition is true, reqfifo_rready gets assigned otherwise 1'b0 is assigned
// to rspfifo_rready. In either case, rspfifo_rready should be false as when under_rst=1, we can't
// get rvalid_o and with no rvalid_o there shouldn't be any rready_i in case of u_reqfifo.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can refer to the previous condition to make this argument quite a bit shorter:

// By the same argument as that given for the previous condition, the u_rspfifo storage cannot be
// nonempty when the under_rst flag is true. But u_rspfifo was has a Pass parameter of 1, which
// would give another way for rvalid_o to be true. For that to apply, we would need wvalid_i to be
// true, which is rspfifo_wvalid in tlul_adapter_sram. This depends on reqfifo_rvalid, which can
// only be true when u_reqfifo is nonempty. The reasoning for the previous condition shows that this
// cannot happen.

Comment on lines +224 to +218
// For u_sramreqfifo, the reasoning is similar as u_reqfifo i.e when under_rst=1 we can't get
// rvalid_o. For rready_i, it comes in from u_tl_adapter_rom and gets assigned by rspfifo_wvalid.
// As explained above in the case of u_rspfifo about how to get rspfifo_wvalid which requires
// reqfifo_rvalid true to set itself true which is impossible if under_rst=1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can be lazier here, with something like this:

// Since u_sramreqfifo has Pass=0, this condition cannot happen for the same reason as the analogous
// condition for u_reqfifo, argued above.

Comment on lines +233 to +230
// For u_reqfifo, if wready_o=0 this means that the fifo is either in reset or full. wvalid_i comes
// from u_tl_adapter_rom as reqfifo_wvalid. It gets continuous assignment through a_ack. a_ack is
// true if we get a_valid coming from u_sram_byte as one of the ports of tl_i_int and a_ready going
// into u_sram_byte as one of the ports of tl_o_int. In order to set tl_o_int.a_ready as true, we
// need reqfifo_wready as true. Hence, if we don't have wready_o as true, we can't get
// tl_o_int.a_ready in u_tl_adapter_rom which means that a_ack should be false leading to wvalid_i
// being false.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought a little bit about this and I think there's probably a shorter chain of reasoning: we don't actually need to say anything about what the ready and valid signals mean in this case. Something like this, maybe?

// The wvalid_i signal in u_reqfifo comes from reqfifo_valid in tlul_adapter_sram, which equals
// a_ack. For that to be true, tl_a_int.a_ready must be true. That signal is only true if
// reqfifo_wready is true, but that signal is wready_o.

Comment on lines +243 to +237
// For u_rspfifo, wvalid_i comes from u_tl_adapter_rom as rspfifo_wvalid. In order to set it true,
// we need reqfifo_rvalid true. Which means that we are reading the write that happened earlier and
// u_rspfifo needs to respond to that. If u_rspfifo is responding now then it means that it is not
// full and we can have wready_o with wvalid_i.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This took me a few seconds to properly understand, and I think that it could be explained more clearly (for me, at least!). Something like this, maybe?

// The u_rspfifo instance in tlul_adapter_sram can never give any backpressure through the wready_o
// signal. This is because u_reqfifo will always be at least as full as u_rspfifo, each item in
// u_rspfifo is a response to a request that is still stored in u_reqfifo. The request is stored in
// order to be able to supply d_size and d_source in the TL response.
//
// If w_valid_i is true in u_rspfifo, this is the response to some request which must be stored in
// u_reqfifo, which implies there is a slot to store it.

INSTANCE: tb.dut.u_tl_adapter_rom.u_rspfifo
Condition 3 "786039886" "(wvalid_i & wready_o & ((~gen_normal_fifo.under_rst))) 1 -1" (2 "101")

// For u_sramreqfifo, we can get wready_o=1 when under_rst=0 if the sram fifo is full. But we can't
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you mean wready_o=0 here? I'd also say "... we only get wready_o=0 ..." to make it clear how the implication is supposed to go.

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