Require

require statements can be used in coordination with supports statements to automate pin assignment. When we use a require statement it creates an abstract port. We can use this abstract port like any other port and JITX will handle mapping that abstract port to a concrete port on a component.

The require statement is valid in the following contexts:

Signature

  ; Implicit `self` form
  require <NAME>:<TYPE>
  require <NAME>:<TYPE>[<ARRAY>]

  ; Explicit form
  require <NAME>:<TYPE> from <INST>
  require <NAME>:<TYPE>[<ARRAY>] from <INST>
  • &lt;NAME> - Name of the created abstract port in this context. This must be a unique symbol name in the current context.
  • &lt;TYPE> - The Bundle type for the requested abstract port.
  • &lt;ARRAY> - Optional Array Initializer for constructing an array of abstract port.
  • &lt;INST> - The Instance from which we are requesting abstract port.
    • In the Implicit form, this value is self by default.
    • In the Explicit form, we must provide a ref to a specific module or component instance in the current context.

Usage

Basic Pin Assignment

pcb-bundle i2c:
  pin sda
  pin scl

pcb-module top-level:
  inst mcu : stm32f405G7

  require bus:i2c from mcu

  inst sensor : temp-sensor
  net (bus, sensor.i2c-bus)

  inst R : chip-resistor(4.7e3)[2]
  net (bus.sda, R[0].p[1])
  net (bus.scl, R[1].p[1])

This is a typical use case for pin assignment in a microcontroller circuit. Here we are requesting one of the 3 available I2C ports on the SM32F405 and constructing an abstract port that will map to one of them depending on what other require statements exists as well as the board conditions.

The bus abstract port can be used like any other port on a component or module. We can use the net statement to connect it to other ports. We can use dot notation to connect to individual pins of the abstract port.

Abstract Port Array

pcb-bundle gpio:
  pin p

pcb-module top-level:
  inst mcu : stm32f405G7

  val num-sw = 4
  require sw-inputs:gpio[ num-sw ] from mcu

  inst switches : momentary-switch[ num-sw ]
  for i in 0 to num-sw do:
    net (sw-inputs[i].p, switches[i].p[1])

Like other inst or net declarations, we can construct an array of abstract ports withe [] syntax. Here we construct 4 GPIO abstract ports requested from the mcu instance.

We can then connect these individual gpio pins to other instance ports, like the momentary-switch instances.

Use of require inside supports

We often want to cascade the construction of abstract ports by using require statements inside supports statements.


pcb-component stm32:
  port PA : pin[32]
  ...

  pcb-bundle I2C0_SDA:
    pin p

  supports I2C0_SDA:
    option:
      I2C0_SDA.p => self.PA[1]
    option:
      I2C0_SDA.p => self.PA[7]

  pcb-bundle I2C0_SCL:
    pin p

  supports I2C0_SCL:
    option:
      I2C0_SCL.p => self.PA[2]
    option:
      I2C0_SCL.p => self.PA[6]

  supports i2c:
    require sda0:I2C0_SDA
    require scl0:I2C0_SCL
    i2c.sda => sda0
    i2c.sda => scl0

pcb-module top-level:

  inst mcu : stm32
  require bus:i2c from mcu

In this example, we define ad-hoc pcb-bundle definitions I2C0_SDA and I2C0_SCL that are only accessible within this component's context. The supports statements for these two bundle types effectively make private pending ports that can only be used within this context.

Finally - we make a supports i2c: statement that constructs an externally accessible pending port for the i2c bundle type. The bus abstract port that we are ultimately able to connect to the rest of our system consists of:

  • bus.sda =>
    • mcu.PA[1] OR
    • mcu.PA[7]
  • bus.scl =>
    • mcu.PA[2] OR
    • mcu.PA[6]

Notice that in the supports i2c: statement, the require statement uses the Implicit form (ie, the lack of a from <INST> part of the statement). This means that this require statement is targeting self. This statement is exactly the same as:

    require sda0:I2C0_SDA from self

Check out restrict

There is also the restrict statement which provide another method of defining the constraints for the pin assignment problem. The restrict statement operates on the abstract port instances defined by the require statement.