•  main page
•  about BLK
•  products
•  services
•  library
•  links
•  resume
•  contact

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_PHASEg" 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.