Drivers

While the VectorBuilder already simplifies the programatic generation of vectors it is still a very low level scheme to interact with a DUT.

This section introduces the drivers currently supported by dumpling that provide functions for chip interaction at a much higher abstraction-level.

Important

Each driver reports the set of logical pins that it is going to interact with. The driver will only assign values to these signals. Any other signal that might have been declared during instantiation of the VectorBuilder instance will not be affected at all. E.g. lets suppose you wanted to generate a vector file that, in addition to the defined JTAG pins of the JTAG driver, also contains a global chip_reset pin. Now have a look at the following example:

builder.chip_reset = 0
vectors = jtag_driver.jtag_reset(comment="Resetting the jtag iface")
builder.chip_reset = 1
vectors += jtag_driver.jtag_idle_vectors(count=10, comment="Deasserting global reset and idling JTAG")

Since you altered the value of chip reset before generating vectors using the JTAGDriver instance, each vector generated by the driver will have the value ‘0’ assigned to chip_reset while each vector generated by the second interaction driver will have the chip_reset pin assume the value ‘1’.

JTAG

Logical Pins

The JTAG Driver uses the following logical pins:

“tck”

The JTAG clock pin

“tms”

The Test Mode select pin

“trst”

The test logic reset pin

“tdi”

Test data input input

“tdo”

Test data output

Description

The JTAG driver infrastructure is split into several different entities in order to make it easier to add support for new JTAG Taps and to make the TAP drivers agnostic to the length of the JTAG chain in a particular chip (how many other TAPs are connected to the same chain). The most basic interaction is provided by the JTAGDriver class. Like all drivers it is instantiated by providing its constructor with an initialized VectorBuilder instance. The JTAGDriver is then configured to match the actual JTAG chain of the target DUT. For each TAP in the JTAG chain, an instance of JTAGTap or its subclasses is added in the order the TDI signal traverses them. The baseclass JTAGTap serves the key purpose of informing the JTAGDriver driver instance about the position and IR length of each JTAG tap in the chain. Here is an example:

Jtag_chain = JTAGDriver(vector_builder=builder)
tap1 = PULPJTAGTap(jtag_chain)
tap2 = JTAGTap("Dummy Tap", ir_size=5, driver=jtag_chain)
jtag_chain.add_tap(tap1)
jtag_chain.add_tap(tap2)

In this example we configure a JTAGDriver driver instance with two TAPs. The first one being an instance of PULPJTAGTap and the second one being some other generic TAP that we don’t need to interact with but nonetheless inform the driver abouth its presence so it can adjust the vectors to account for the additional chain element during JTAG interaction.

Note that we first instantiate the individual taps by providing them a handle to the JTAGDriver driver instance. The subclasses of JTAGTap use this handle to interact with the chain through the driver without having to be aware of the presence of other TAPs on the same chain.

Once configured, the JTAGDriver driver instance can be used to directly interact with the jtag chain (which is what the subclasses of JTAGTap do internally for high level operations). Here is an example of such an interaction:

vectors = scan_chain.jtag_set_IR(tap1, "010011", comment="Selecting the FLL config register")
vectors += scan_chain.jtag_set_DR(tap1, "1110", comment="Write 0xE to FLL config register")

Since driver functions almost always return lists of vectors we can conveniently append them using the += operator.

Attention

Since the JTAG driver is already aware of the presence of other JTAG taps (e.g. Dummy TAP “tap2” in our example) we don’t have to account for it anymore when chosing the IR or DR values. The bitstrings are automatically padded according to the chain configuration. Read the documentation of JTAGDriver.jtag_set_ir and JTAGDriver.jtag_set_ir for additional details.