| # TL-UL Protocol Checker |
| |
| # TileLink-UL Protocol Checker |
| |
| |
| ## **Overview** |
| |
| This document details the protocol checker |
| [tlul_assert.sv](https://github.com/lowRISC/opentitan/blob/master/hw/ip/tlul/rtl/tlul_assert.sv) |
| for TL-UL (TileLink Uncached Lightweight), based on |
| [TileLink specification version 1.7.1](https://sifive.cdn.prismic.io/sifive%2F57f93ecf-2c42-46f7-9818-bcdd7d39400a_tilelink-spec-1.7.1.pdf). |
| |
| The next sections list the checks for each signal of TL-UL channels A and D. |
| More details: |
| |
| * The source fields (`a_source` and `d_source`) identify in-flight |
| transactions rather than physical agents. A single agent can use multiple |
| source IDs to track multiple outstanding transactions. See spec section 5.4 |
| "Source and Sink Identifiers" for more details. |
| * The source fields are `TL_AIW` bits wide (defined in |
| [tlul_pkg.sv](https://github.com/lowRISC/opentitan/blob/master/hw/ip/tlul/rtl/tlul_pkg.sv)). |
| Therefore, there can be up to 2<sup>TL_AIW</sup> outstanding |
| requests at the same time. To keep track of these outstanding requests, the |
| protocol checker stores pending requests in the array `pend_req` of depth |
| `TL_AIW`, and removes them once their corresponding response has been received. |
| * A request can be responded within the same cycle as the request message is |
| accepted. Therefore, in each clock cycle, the protocol checker first processes |
| requests and thereafter responses. |
| * The package |
| [tlul_pkg.sv](https://github.com/lowRISC/opentitan/blob/master/hw/ip/tlul/rtl/tlul_pkg.sv) |
| defines the structs for channels A and D. |
| * In below tables, "known" means that a signal should have a value other |
| than X. |
| * The protocol checker has a parameter `EndpointType` which can either be |
| `"Host"` or `"Device"`. The difference between the `"Host"` and `"Device"` |
| variant is that some of the properties are formulated as SV assumptions in the |
| former, whereas the same properties are formulated as SV assertions in the |
| latter (and vice versa). The behavior of these two checkers in DV simulations |
| is identical, but in formal verification, this distinction is needed (otherwise |
| some of the assertions would have to be disabled). |
| |
| ## **Request Channel (Channel A)** |
| |
| Below table lists all channel A signals and their checks. |
| In `"Device"` mode some of these properties are assumptions (`_M` suffix) and in `"Host"` mode they are assertions (`_A` suffix). |
| |
| <table> |
| <tr> |
| <td><strong>Signal</strong> |
| </td> |
| <td><strong>Checks </strong>(assertion name: description) |
| </td> |
| </tr> |
| <tr> |
| <td>a_opcode |
| </td> |
| <td><strong>legalAOpcode_[M/A]</strong>: Only the following 3 opcodes are legal: |
| Get, PutFullData, PutPartialData. See spec section 6.2. |
| </td> |
| </tr> |
| <tr> |
| <td>a_param |
| </td> |
| <td><strong>legalAParam_[M/A]</strong>: This field is reserved, it must be 0. See |
| spec section 6.2. |
| </td> |
| </tr> |
| <tr> |
| <td>a_size |
| </td> |
| <td><strong>sizeMatchesMask_[M/A]</strong>: a_size can be calculated from a_mask |
| as follows: 2<sup>a_size</sup> must equal $countones(a_mask). See spec section |
| 4.6. |
| <p> |
| <strong>aKnown_A</strong>: Make sure it's not X when a_valid is high. |
| </td> |
| </tr> |
| <tr> |
| <td>a_source |
| </td> |
| <td><strong>pendingReqPerSrc_[M/A]</strong>: There should be no more |
| than one pending request per each source ID. See spec section 5.4. |
| <p> |
| <strong>aKnown_A</strong>: Make sure it's not X when a_valid is high. |
| </td> |
| </tr> |
| <tr> |
| <td>a_address |
| </td> |
| <td><strong>addrSizeAligned_[M/A]</strong>: a_address must be aligned to |
| a_size: a_address & ((1 << a_size) - 1) == 0. See spec section 4.6. |
| <p> |
| <strong>aKnown_A</strong>Make sure it's not X when a_valid is high. |
| </td> |
| </tr> |
| <tr> |
| <td>a_mask |
| </td> |
| <td><strong>contigMask_[M/A]</strong>: a_mask must be contiguous for Get |
| and PutFullData (but not for PutPartialData). See spec sections 4.6 and 6.2. |
| <p> |
| <strong>sizeMatchesMask_[M/A]</strong>: See a_size above. |
| <p> |
| <strong>aKnown_A</strong>Make sure it's not X when a_valid is high. |
| </td> |
| </tr> |
| <tr> |
| <td>a_data |
| </td> |
| <td><strong>aDataKnown_[M/A]</strong>: a_data should not be X for opcodes |
| PutFullData and PutPartialData (it can be X for Get). Bytes of a_data, whose |
| corresponding a_mask bits are 0, can be X. See spec section 4.6. |
| </td> |
| </tr> |
| <tr> |
| <td>a_user |
| </td> |
| <td><strong>aKnown_A</strong>Make sure it's not X when a_valid is high. |
| </td> |
| </tr> |
| <tr> |
| <td>a_valid |
| </td> |
| <td><strong>aKnown_A</strong>: Make sure it's not X (except during reset). |
| </td> |
| </tr> |
| <tr> |
| <td>a_ready |
| </td> |
| <td><strong>aReadyKnown_A</strong>: Make sure it's not X (except during |
| reset). |
| </td> |
| </tr> |
| </table> |
| |
| ## **Response Channel (Channel D)** |
| |
| Below table lists all channel D signals and their checks. |
| In `"Device"` mode some of these properties are assertions (`_A` suffix) and in `"Host"` mode they are assumptions (`_M` suffix). |
| |
| <table> |
| <tr> |
| <td><strong>Signal</strong> |
| </td> |
| <td><strong>Checks </strong>(assertion name: description) |
| </td> |
| </tr> |
| <tr> |
| <td>d_opcode |
| </td> |
| <td><strong>respOpcode_[A/M]</strong>: If the original request was Get, |
| then the corresponding response must be AccessAckData. Otherwise, the response |
| must be AccessAck. See spec section 6.2. |
| </td> |
| </tr> |
| <tr> |
| <td>d_param |
| </td> |
| <td><strong>legalDParam_[A/M]</strong>: This field is reserved, it must be 0. See |
| spec section 6.2. |
| </td> |
| </tr> |
| <tr> |
| <td>d_size |
| </td> |
| <td><strong>respSzEqReqSz_[A/M]</strong>: The response must have |
| the same size as the original request. See spec section 6.2. |
| </td> |
| </tr> |
| <tr> |
| <td>d_source |
| </td> |
| <td><strong>respMustHaveReq_[A/M]</strong>: For each response, there must have |
| been a corresponding request with the same source ID value. See spec section |
| 5.4. |
| <p> |
| <strong>noOutstandingReqsAtEndOfSim_A</strong>: Make sure that there are no |
| outstanding requests at the end of the simulation. |
| <p> |
| <strong>dKnown_A</strong>: Make sure it's not X when d_valid is high. |
| </td> |
| </tr> |
| <tr> |
| <td>d_sink |
| </td> |
| <td><strong>dKnown_A</strong>: Make sure it's not X when d_valid is high. |
| </td> |
| </tr> |
| <tr> |
| <td>d_data |
| </td> |
| <td><strong>dDataKnown_[A/M]</strong>: d_data should not be X for AccessAckData. |
| Bytes of d_data, whose corresponding mask bits of the original request are 0, |
| can be X. See spec section 4.6. |
| </td> |
| </tr> |
| <tr> |
| <td>d_error |
| </td> |
| <td><strong>dKnown_A</strong>Make sure it's not X when d_valid is high. |
| </td> |
| </tr> |
| <tr> |
| <td>d_user |
| </td> |
| <td><strong>dKnown_A</strong>Make sure it's not X when d_valid is high. |
| </td> |
| </tr> |
| <tr> |
| <td>d_valid |
| </td> |
| <td><strong>dKnown_A</strong>: Make sure it's not X (except during reset). |
| </td> |
| </tr> |
| <tr> |
| <td>d_ready |
| </td> |
| <td><strong>dReadyKnown_A</strong>Make sure it's not X (except during |
| reset). |
| </td> |
| </tr> |
| </table> |