Using DFRAME# to Differentiate Address Phases
[from Data Phases of PCI Bus Transactions]
This article was orginally published by Future Plus
Systems Corporation in their 3Q 1995 edition of "The Bus Analyzer",
a newsletter targeted at users of the HP16500 series Logic Analyzer and
their legacy FS16P32E
interface card.
My 9323A
PCI Extender and Interface Board is a cost-effective alternative to
expensive, high-end interface cards, suitable for most hardware and software
developers, hobbyists, and anyone interested in learning how PCI devices
work at the hardware level.
* * *
Using DFRAME# to Differentiate Address Phases
Requirements: HP 16500 series logic analyzer mainframe with 16550 or
16555 Timing/State module; 9323A or Future+ FS16P32E interface card (later
became the FS2000),
Future Plus Systems Inverse Assembler for PCI bus transactions.
By adding a fast PAL to your PCI preprocessor board, you can easily differentiate
the address/command phase from the data phase for enhanced state analysis.
Although strictly speaking, the second load on CLK and FRAME# makes the
device noncompliant, it is a piece of test equipment and the loading
does not adversely affect operation, even if the device under test is
plugged in the top connector.
Keeping wire lengths as short as possible, attach a 5 ns 16V8 to the
preprocessor connected as follows:
The following equations are programmed in to generate DFRAME# which becomes
available on the USER 2 input of the analyzer configuration. Alternatively
you could use USER 1. Do not use pod 1 bit 15 even though it appears unassigned
in the HP 16550 format menu. Create the DFRAME label in the format menu.
;PALASM Design Description
;-------------------------- Declaration Segment ----------
TITLE pal to generate DFRAME for logic analyzer
PATTERN dframe.pds
CHIP _dframe PALCE16V8
;-------------------------- PIN Declarations -------------
PIN 1 clk
PIN 9 /frame
PIN 10 gnd
PIN 11 /oe
PIN 15 /dframe
PIN 20 vcc
;-------------------------- Boolean Equation Segment ------
EQUATIONS
dframe := frame ; dframe follows frame 1 clk later
;----------------------------------------------------------
After assigning the DFRAME# label in the analyzer configuration, new
terms can be defined in the trigger menu:
A_PHASE = (FRAME# = 0)
(DFRAME# = 1) ; address/command phase
D_PHASE = (IRDY# = 0) (TRDY# = 0) ; data transfer phase
A_PHASE will only be true on the first CLK edge of any PCI transaction
including a burst. D_PHASE will only be true for data transfers. State
listings can therefore be set up to exclude all wait states, or further
qualified to store only particular transaction types. This is excellent
for timing software operations or hardware events, and for determining
burst lengths or merge behavior. The advantage of this method over invasm
suppression is that only the states you need to look at are stored, increasing
the visible event window. The disadvantage is that the state listings
can appear different due to invasm confusion. However, they are easily
interpreted and will not be in error (i.e., the inverse assembler will
never show incorrect information; convince yourself by comparing any qualified
state-mode listing against an identically triggered timing-mode waveform).
This is best demonstrated by example.
Figure 1 shows how bursts get displayed. State 2 is a 16-bit transfer
to A18D2-3. State 3 (which was merged) and state 4 continue the burst
up to A18D9. State 5 is a new burst transaction starting at A18DA. The
user is cautioned to use this simplified form only if target-initiated
termination is impossible or irrelevant to your trace, since you will
lose the ends of these cycles.
Figure 1. Memory write burst.
Label >
Base >
--------
|
PCI BUS TRANSACTIONS
REV 2.2
--------------------- |
Time
Relative
--------- |
C/B3_0
Binary
------ |
1
|
MEM WRITE ADR=000A18D0
|
96 ns |
0111 |
2
|
D32=ABCDxxxx
|
72 ns |
0011 |
3
|
D32=ABCDABCD
|
96 ns |
0000 |
4
|
D32=xxxxABCD
|
64 ns |
1100 |
5
|
MEM WRITE ADR=000A18D8
|
104 ns |
0111 |
6
|
D32=ABCDxxxx
|
64 ns |
0011 |
7
|
D32=ABCDABCD
|
104 ns |
0000 |
8
|
D32=xxxxABCD
|
64 ns |
1100 |
Analyzer trigger setup:
1: While storing "A_PHASE+D_PHASE"
TRIGGER on "A_PHASE
g" 1 time
g=(FRAME=0
ADDR=000Axxxx)
2: Store "A_PHASE+D_PHASE"
Figure 2 includes additional qualification of stored states and includes
the "i" term to store retries (which, if excluded as in Fig.
1, will produce incorrect results that appear as "WAIT" states
which simply cannot be stored should they occur). The only
other misleading result that can happen is in the case of master abort.
The storage conditions inhibit recording of the ends of master aborted
cycles. Master aborts are easy to identify, however: they will appear
as "WAIT-TARGET AND INITIATOR NOT READY" due to invasm confusion
(more on this later). Note that since the store conditions prevent any
wait states from being recorded, such a reference uniquely identifies
master aborts, which are usually rare events (often limited to bios configuration
accesses and memory activity in the unpopulated upper areas of the 4-gig
space). Master-aborted DAC Snoop cycles are also permitted in PCI 2.1.
Figure 2. I/O reads with retries stored.
Label >
Base >
--------
|
PCI BUS TRANSACTIONS
REV 2.2
--------------------- |
Time
Relative
-------- |
STOP
Binary
----- |
0
|
I/O READ ADR=00000064 |
3.624 us |
1
|
1
|
D32=xxxxxx1D |
1.160 us |
1
|
|
|
|
|
2
|
I/O READ ADR=00000064 |
536 ns |
1
|
3
|
D32=xxxxxxAD |
1.192 us |
1
|
|
|
|
|
4
|
I/O READ ADR=00000064 |
568 ns |
1
|
5
|
D32=xxxxxx1F |
1.168 us |
1
|
...
|
|
|
|
16
|
I/O READ ADR=00000064 |
432 ns |
1
|
17
|
STOP-NO
DATA XFERED-RETRY |
168 ns |
0
|
|
|
|
|
18
|
I/O READ ADR=00000064 |
136 ns |
1
|
19
|
STOP-NO
DATA XFERED-RETRY |
160 ns |
0
|
Analyzer trigger setup:
1: While storing "A_PHASE+D_PHASE"
TRIGGER on "A_PHASE
g" 1 time
g=(FRAME=0
ADDR=00000064 CBE=001x)
2: Store "A_PHASE+D_PHASE+i"
i=(IRDY=0
STOP=0)
Sometimes more complicated trigger and storage conditions will be required,
such as when you only care about time between the beginnings of long bursts
of data transfers rather than the actual data (Figure 3 uses the timer
to expire the transfer term).
Figure 4 will store every bios configuration access during the boot process.
It could easily be modified to capture other activities such as writes
to the expansion rom base address register or the register-level programming
activities during Windows 95 bootup. Keep in mind that you don't need
to trigger at all to get a great state recording! This method works particularly
well when looking for the most recent in a long string of repeated events.
Take notice to the appearance in Figure 4 of the master aborts at states
377-379 and how the missing end interfered with the address phase whose
transfer was at state 380. Figure 5 adds a term that helps unconfuse the
inverse assembler (IA) by attempting to store the ends of master aborts
(with relative success). The weakness is that the shortest timer HP allows
is 400 ns. Three clocks (100 ns) would be completely reliable; in this
example we are counting on system bios not executing master aborts closer
than 400 ns (usually but not always true). Note how the master aborted
cycle has changed to "WAIT-NO DEVICE SELECT." The IA still can't
tell it was really a master abort, but the indication is more accurate
than before. Careful observers might also notice that the byte enables
in states 550 and 553 are for either Device ID then Vendor ID, not both
as implied by the IA. A future revision will indicate unenabled bytes
in configuration space appropriately.
Figure 3. Use of timer to disqualify the ends of long data transfers.
Label>
Base >
------ |
PCI
BUS TRANSACTIONS
REV 2.2
------------------- |
Time
Absolute
-------- |
C/B3_0
Binary
------
|
DFRAME
Binary
------ |
STOP
Binary
------ |
DEVSEL
Binary
------ |
ADDR
Hex
---- |
2
|
MEM
WRITE ADR=000A0004 |
168
ns |
0111 |
1
|
1
|
1
|
000A0004 |
3
|
D32=ABCD1234 |
232
ns |
0000 |
0
|
1
|
0
|
ABCD1234 |
4
|
D32=ABCD1234 |
336
ns |
0000 |
0
|
1
|
0
|
ABCD1234 |
5
|
D32=ABCD1234 |
400
ns |
0000 |
0
|
1
|
0
|
ABCD1234 |
6
|
D32=ABCD1234 |
504
ns |
0000 |
0
|
1
|
0
|
ABCD1234 |
7
|
D32=ABCD1234 |
568
ns |
0000 |
0
|
1
|
0
|
ABCD1234 |
8
|
MEM
WRITE ADR=000A0100 |
5.360
us |
0111 |
1
|
1
|
1
|
000A0100 |
9
|
D32=ABCD1234 |
5.424
us |
0000 |
0
|
1
|
0
|
ABCD1234 |
10
|
D32=ABCD1234 |
5.520
us |
0000 |
0
|
1
|
0
|
ABCD1234 |
11
|
D32=ABCD1234 |
5.592
us |
0000 |
0
|
1
|
0
|
ABCD1234 |
12
|
D32=ABCD1234 |
5.688
us |
0000 |
0
|
1
|
0
|
ABCD1234 |
13
|
MEM
WRITE ADR=000A0200 |
10.78
us |
0111 |
1
|
1
|
1
|
000A0200 |
14
|
D32=ABCD1234 |
10.85
us |
0000 |
0
|
1
|
0
|
ABCD1234 |
15
|
D32=ABCD1234 |
10.94
us |
0000 |
0
|
1
|
0
|
ABCD1234 |
Analyzer trigger setup:
1: While storing "no state"
TRIGGER on "i" 1 time
i=(FRAME=0
ADDR=000Axxxxx CBE=011x)
2: While storing "A_PHASE+((D_PHASE+g)
timer2<400ns)"
Then find "A_PHASE" 1 time
Else on "no state" go to level 2
TimerControl="S"
g=(IRDY=0
STOP=0)
3: Store "A_PHASE+((D_PHASE+g)
timer2<400ns)"
On "A_PHASE" go to level 2
TC="S"
Figure 4. Configuration accesses.
Label>
Base >
------ |
PCI
BUS TRANSACTIONS
REV 2.2
------------------- |
ADDR
Hex
---- |
C/B3_0
Binary
------
|
STOP
Bina
---- |
DEVSEL
Binary
------ |
IDSEL
Binary
------ |
FRAME
Binary
------ |
IRDL
Bin
----
|
TRDY
Bin
---- |
Time
Relative
-------- |
376
|
CONFG
READ ADR=80000000
FUNC=0 REG=0 TYPE=00 |
80000000 |
1010 |
1
|
1
|
0
|
0
|
1
|
1
|
7.085
ms |
377
|
WAIT-TARGET AND INITIATOR NOT READY |
40000000 |
1010 |
1
|
1
|
0
|
0
|
1
|
1
|
30.56
us |
378
|
WAIT-TARGET AND INITIATOR NOT READY |
20000000 |
1010 |
1
|
1
|
0
|
0
|
1
|
1
|
29.39
us |
379
|
WAIT-TARGET AND INITIATOR NOT READY |
10000000 |
1010 |
1
|
1
|
0
|
0
|
1
|
1
|
28.24
us |
380
|
DEVICE
ID=3207 VENDOR ID=100C |
3207100C |
1100 |
1
|
0
|
1
|
1
|
0
|
0
|
96
ns |
381
|
IDLE |
3207100C |
1100 |
1
|
1
|
1
|
1
|
1
|
1
|
32
ns |
Analyzer trigger setup:
1: While storing "no state" TRIGGER on "IDLE" 1 time
post store 93%, branches taken stored.
2: While storing "no state" Then find "C_PHASE" 1
time
> Press STOP after boot completes.
3: While storing "C_PHASE"
Then find "D_PHASE+g" 1 time
C_PHASE=(FRAME=0
DFRAME=1 CBE=101x)
g=(IRDY=0
STOP=0)
4: Store "C_PHASE+D_PHASE+g"
On "IDLE" goto level 2
Figure 5. Configuration accesses with master abort fix.
Label>
Base >
------ |
PCI
BUS TRANSACTIONS
REV 2.2
------------------- |
ADDR
Hex
---- |
C/B3_0
Binary
------
|
STOP
Bina
---- |
DEVSEL
Binary
------ |
IDSEL
Binary
------ |
FRAME
Binary
------ |
IRDL
Bin
----
|
TRDY
Bin
---- |
Time
Relative
-------- |
546
|
CONFG
READ ADR=80000000
FUNC=0 REG=0 TYPE=00 |
20000000 |
1010 |
1
|
1
|
0
|
0
|
1
|
1
|
568
ns |
547
|
WAIT-NO DEVICE SELECT |
20000000 |
1100 |
1
|
1
|
0
|
1
|
0
|
1
|
32
ns |
548
|
IDLE |
20000000 |
1100 |
1
|
1
|
0
|
1
|
1
|
1
|
136
ns |
549
|
CONFG
READ ADR=10000000
FUNC=0 REG=0 TYPE=00 |
10000000
|
1010 |
1
|
1
|
1
|
0
|
1
|
1
|
26.90
us |
550
|
DEVICE ID=3206 VENDOR ID=100C |
3206100C |
0011 |
1
|
0
|
1
|
1
|
0
|
0
|
96
ns |
551
|
IDLE |
3206100C |
0011 |
1
|
1
|
1
|
1
|
1
|
1
|
32
ns |
552
|
CONFG
READ ADR=10000000
FUNC=0 REG=0 TYPE=00 |
10000000 |
1010 |
1
|
1
|
1
|
0
|
1
|
1
|
568
ns |
553
|
DEVICE ID=3206 VENDOR ID=100C |
3206100C |
1100 |
1
|
0
|
1
|
1
|
0
|
0
|
104
ns |
554
|
DLE |
3206100C |
1100 |
1
|
1
|
1
|
1
|
1
|
1
|
32
ns |
555
|
CONFG
READ ADR=1000000C
FUNC=0 REG=3 TYPE=00 |
1000000C |
1010 |
1
|
1
|
1
|
0
|
1
|
1
|
24.38
us |
556
|
BIST=00
Hdr_Typ=00 Lat_Tmr=00 CLS=00 |
00000000 |
1011 |
1
|
0
|
0
|
1
|
0
|
0
|
96
ns |
557
|
DLE |
00000000 |
1011 |
1
|
1
|
0
|
1
|
1
|
1
|
32
ns |
Analyzer trigger setup:
1: While storing "no state" TRIGGER on "IDLE" 1 time
2: While storing "no state" Then find "C_PHASE" 1
time
TimerControl="S"
3: While storing "C_PHASE"
TC="S"
Then find "D_PHASE+g+(j
timer2>400ns)" 1 time
j=(FRAME=1
DEVSEL=1 IRDY=0)
4: Store "C_PHASE+D_PHASE+g+(j
timer2>400ns)"
TC="S"
On "IDLE" goto level 2
# # #
If you are interested in purchasing a product, developing
a new one, or discussing how I can help you make your current technology
or software products better, email
me.
|