Skip to content

Check Statements

Checks allow us to automatically verify our designs. We can write arbitrary code to scan through our designs, inspect the data and make sure the circuit will work as intended. JITX will generate a well-formatted report on the results of all checks; prompting users to enter more data or pointing out errors in the design.

We can define checks specific to a circuit or component. With checks, circuit generators can check themselves for correct usage, thus ensuring safe reusability.

Signature

pcb-check check-name (arg1:Type, ...) :
  ; One assertion (or sub-check) 
  #CHECK(
    ; Required field: a boolean expression
    condition = <Exp>
    ; Optional metadata
    name = <Printable>
    description = <Printable>
    category = <Printable>
    subcheck-description = <Printable>
    pass-message = <Printable>
    fail-message = <Printable>
    info-message = <Printable>
    locators = <Tuple<JITXDef|JITXObject>> 
  )
  ; More #CHECK assertions as needed

pcb-module main-module :
  ; Apply a named check to a module or component
  check <String>(<Exp>, ...)
  ...

; Run all checks in the current design
; JITX writes a report on all check results to the given filename
run-checks(<Filename>)

There are three key components to writing and using a check.

First, we define the check in the pcb-check code block. The check itself can take arguments; usually we will parameterize the check by a JITX object that we want to verify. A pcb-check can contain any number of assertions generated by the #CHECK syntax. The only required field in an assertion is its condition: this can be an arbitrary expression, but must return a boolean. The remaining fields are metadata for the check. When JITX runs checks, it will produce a report on the result of all of the checks, which will contain information from the checks' metadata. Most of the fields are Printable expressions used to describe the checks' purpose and status. The one exception is the locators field: a set of JITX objects or definitions, allowing the final report to link back the code that passed or failed a check.

Second, we use the check statement to apply the validation logic defined above to a pcb-module or pcb-component.

Third, we use the command run-checks to actually run all of the checks on our design and write out the resulting report to a specified file.

Watch Out! - We cannot define both info-message and fail-message. If info-message is defined, an assertion failure will register as "incomplete"; otherwise it will register as a check failure

Usage

Below is an example check for AEC ratings and its usage.

; We will check that a given component has an AEC Q200 rating
; by verifying that it has a property called "aec-rating".
; `component` is the argument to our check
pcb-check aec-q200 (component:JITXObject):
  ; One assertion
  #CHECK(
    ; Check name
    name =                 "Automotive rating"
    ; Check description
    description =          "Check that a passive component is AEC Q200 rated"
    ; The check itself: does the component have a property named `aec-rating`?
    condition =            has-property?(component.aec-rating),
    ; Check category
    category =             "Component Data"
    ; Description of this particular assertion
    subcheck-description = "Check that %_ has a defined aec-rating" % [ref(component)],
    ; Message when the check passes
    pass-message =         "%_ has a property for aec-rating of %_" % [ref(component) property(component.aec-rating)],
    ; Message when the check does not pass
    info-message =         "%_ does not have an aec-rating property attached" % [ref(component)],
    ; Metadata for associating the component's definition with the check. 
    locators =             [instance-definition(component)]
  )

  ; Another assertion
  ; This one checks that a component's `aec-rating` property is the
  ;   string "Q200".
  #CHECK(
    name =                 "Automotive rating"
    description =          "Check that a passive component is AEC Q200 rated"
    condition =            property(component.aec-rating) == "Q200",
    category =             "Component Checks"
    subcheck-description = "Check that %_ is AEC Q200 rated." % [ref(component)],
    pass-message =         "%_ is AEC Q200 rated" % [ref(component)],
    ; This assertion uses a `fail-message` instead of `info-message`.
    ; If the predicate fails the check will fail.
    fail-message =         "%_ is not AEC Q200 rated. Instead has rating %_." % [ref(component) property(component.aec-rating)],
    locators =             [instance-definition(component)]
  )

; Use a check
pcb-module checked-design :
  inst r : create-resistor(1.0)
  check aec-q200(r)

; Run checks and log output.
set-main-module(checked-design)
run-checks("check-output.txt")

We want to check that our components are AEC Q200 rated. In the context of JITX code, there are two ways we might verify that. The first sub-check (the #CHECK statement) looks to see if the component has a property named aec-rating. If it does not, the check will be "incomplete", since we provided an info-message parameter. The second sub-check looks at the property's value. If property(component.aec-rating) is not "Q200", the check fails.

Besides the actual predicate, the most important part of each sub-check is its failure condition. A check is usually a sequence of sub-checks, where all but the last one will have an info-message field. If any of those fail, the check will be "incomplete". Finally, if the last predicate (with its associatedfail-message) fails, the entire check will fail. If a programmer does not set eitherinfo-messageorfail-messagethe assertion defaults to afail-message` of "Failure". The rest of the metadata is simply for producing an informative report.

After defining the pcb-check we can apply it to a specific component with the check aec-q200(some-component) syntax. When we eventually run all checks in our design, this will ensure that some-component has the required AEC Q200 metadata. Finally, we run all of the checks on our design with the run-checks command. This will execute every check in the design and log the results to a text file at the specified filename.