Network Integrity¶
The TCK-level program a production flow plays to test the TAP and the IJTAG network themselves -- IDCODE, the instruction register, BYPASS and every unimplemented opcode, every TAP state transition with each register held in Pause at 0 and at 1, each SIB and ScanMux arm opened alone, the network held still under SAMPLE/PRELOAD and through Pause, each WRITE instrument written and read back, a TMS reset -- with the TDO it expects from warptap's own TAP and network models. See the module docstring below for the tests in order and for how a READ instrument bound to a design signal makes its TDO bits don't-care.
from warptap import build_integrity_program, check_integrity
program = build_integrity_program(graph, root)
# Your harness: drive tms/tdi/trst_n for one TCK period, return tdo sampled before TCK rises.
observed = [tck_period(c.tms, c.tdi, c.trst_n) for c in program.cycles]
result = check_integrity(program, observed)
assert result.passed, result.failures # the first mismatch of each failing test
program_json = program.to_json() # a warptap-tck-program file, for a tool without warptap
warptap.tap_integrity ¶
JTAG network-integrity patterns: the TCK-level program a production flow plays through the TAP to test the TAP itself and the IJTAG network behind it, with the TDO it expects.
The TAP and the network are usually left out of scan (they run on TCK/TRST), and are tested through TCK instead, with patterns derived from the network's own description. The program here runs, in order:
reset_instruction: TRST, then a DR scan of the reset instruction's register -- IDCODE (its value, then the fed sentinel after 32 bits), or BYPASS without one;instruction_register: the IR's capture pattern, then the fed sentinel afterir_widthbits (its length); the scan loads BYPASS;bypass: BYPASS's captured 0 and one-bit delay;opcode_<bits>: every unimplemented opcode behaving as BYPASS (exhaustive_opcodes);idcode: an explicit IDCODE load (with IDCODE);- the TAP's own state machine and registers (
tap_paths), each a raw TCK sequence:dr_paths(Run-Test/Idle held, a DR scan paused mid-register and resumed, Exit2-DR -> Update-DR, Update-DR -> Select-DR, Capture-DR -> Exit1-DR without a shift, then the register read whole again),ir_paths(the same for the IR, then Update-IR -> Select-DR),ir_capture_update(Capture-IR -> Exit1-IR -> Update-IR loads the capture pattern),select_ir_reset(Select-IR-Scan -> Test-Logic-Reset, held);idcode_hold/bypass_hold/ir_hold(each register held in Pause-DR/Pause-IR at 0 and at 1 in every bit);idcode_capture/bypass_capture(each register captured while it holds the complement of its capture value). With the rest of the program, every one of the 32 TAP state transitions is taken; network_closed: the network's instruction (EXTEST, or IJTAG_ACCESS for a TAP with anijtag_access_opcode) with every SIB closed -- the network's length and continuity, by an over-shift probe (:mod:warptap.sib_overshift);open_<slot>: each SIB, and each ScanMux arm, opened alone from an all-closed network and probed the same way; thenopen_all, every SIB outside a mux at once;- the network holding still (
network_hold):sample_preload(SAMPLE/PRELOAD puts the network's tail on TDO for the whole scan without selecting the network; with IJTAG_ACCESS,extestand thensample_preload, each a scan through BYPASS), thennetwork_hold(one scan through the network as the probes left it, paused holding an alternating pattern and then its complement, which ends by closing every SIB); write_readback_<instrument>: each WRITE instrument written with an alternating pattern P and read back (Capture-DR captures what it last committed), then ~P, then 0 (write_readback);tms_reset: five TMS=1 cycles (no TRST), then the reset instruction's scan again -- IEEE 1149.1's Test-Logic-Reset reload.
Every probe starts from an all-closed network: :func:~warptap.sib_retarget.
stage_open_sequence leaves an already-open SIB it isn't asked about open, so each probe is
preceded by one scan that closes whatever the last one opened.
The expected TDO comes from :class:~warptap.tap_model.TapModel with
:class:~warptap.sib_model.SibNetworkRegister registered under the network's instruction, and
under SAMPLE/PRELOAD the network's tail (:meth:~warptap.sib_model.SibNetworkRegister.tail;
BYPASS with IJTAG_ACCESS), stepped through every TCK cycle. A READ instrument bound to a
design signal (a live one) captures a value the model can't know, so two models run in
lockstep, their live instruments capturing all 0s and all 1s; a TDO bit on which they
disagree carries a live value and is don't-care (care=False). A probe's fed bits fully
replace the chain's content, so a
captured value reaches TDO but never a SIB's state, and the two models only ever disagree
bit-for-bit. live_values pins a live instrument to a known value instead.
What the program can't see: whatever a TAP register does while another instruction is selected (every DR read starts with a capture), decodes of the opcodes Update-IR never latches (it normalizes every unimplemented one to BYPASS), TDO outside the shift states, and mostly a SIB's capture (it recaptures the state it last committed, which its shift bit normally already holds). A fault simulator grading the program finds those faults undetected.
A consumer plays :attr:IntegrityProgram.cycles one TCK period each: TMS, TDI and TRST_N
applied for the period, TDO sampled before its rising edge on a shift cycle, and passes
what it saw to :func:check_integrity. :meth:IntegrityProgram.to_json writes the same
program as a self-contained file for a consumer without warptap (FaultFlow's jtag
command).
TRST_LEAD_IN
module-attribute
¶
TRST_LEAD_IN: tuple[tuple[int, int, int], ...] = ((0, 0, 0), (0, 0, 0), (0, 0, 1))
TMS_RESET_LEAD_IN
module-attribute
¶
TMS_RESET_LEAD_IN: tuple[tuple[int, int, int], ...] = ((1, 0, 1),) * 5 + ((0, 0, 1),)
TapConfig
dataclass
¶
The TAP the program targets -- rtl/tap_core.v's parameters. Its opcodes are
:mod:warptap.tap_model's (EXTEST 0, IDCODE 1, SAMPLE_PRELOAD 2, BYPASS all 1s), plus
IJTAG_ACCESS at ijtag_access_opcode for a TAP built with one: the network's instruction
then, and EXTEST and SAMPLE/PRELOAD decode to BYPASS.
network_opcode ¶
network_opcode() -> int
The opcode that selects the network: EXTEST's, or IJTAG_ACCESS's.
IntegrityProgram
dataclass
¶
from_json
classmethod
¶
from_json(data: Mapping[str, Any]) -> IntegrityProgram
The inverse of :meth:to_json. The tests carry only their names -- the cycles
are the program.
test_ranges ¶
test_ranges() -> list[tuple[str, int, int]]
(name, start, stop) of each test's cycles, in program order.
to_json ¶
to_json() -> dict[str, Any]
The program as JSON data: tap, tests (name and cycle range), and one
string of 0/1 per cycle field -- tms, tdi, trst_n, shift,
tdo, care -- each character one TCK cycle. tap has an
ijtag_access_opcode only for a TAP with one.
IntegrityTest ¶
Bases: NamedTuple
TckCycle ¶
Bases: NamedTuple
IntegrityResult ¶
Bases: NamedTuple
IntegrityFailure ¶
Bases: NamedTuple
TapIntegrityError ¶
Bases: WarptapError
Raised for a program that can't be built from the given network and options, or an observed TDO stream that doesn't match the program's length.
build_integrity_program ¶
build_integrity_program(graph: PhysicalGraph, root: ModuleInstance, *, tap: TapConfig = TapConfig(), live: Optional[Iterable[str]] = None, live_values: Optional[Mapping[str, int]] = None, margin: int = 8, exhaustive_opcodes: bool = True, write_readback: bool = True, tap_paths: bool = True, network_hold: bool = True) -> IntegrityProgram
The integrity program for graph (and root, its dotted-address tree, for the
write/readback tests) behind a TAP configured as tap.
live names the READ instruments whose capture depends on the design; the default is
every READ instrument bound to a design signal. live_values gives the captured value
of some of them, which makes their bits care bits. margin is the number of sentinel
bits fed past each register's length (at least 1: a register's length shows only when a
fed bit comes back out). exhaustive_opcodes, write_readback, tap_paths and
network_hold each include a group of tests (see the module docstring).
check_integrity ¶
check_integrity(program: IntegrityProgram, observed_tdo: Sequence[object]) -> IntegrityResult
Compare observed_tdo (one TDO value per program cycle) with the expected TDO on
every care cycle, naming the first mismatch of each failing test.
select_instruction ¶
select_instruction(opcode: int, *, ir_width: int = DEFAULT_IR_WIDTH) -> list[_IrOp]
Run-Test/Idle -> shift opcode into the instruction register -> Run-Test/Idle.