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.