JTAG XSVF Parser

Let me start of by apologizing for the nearly two weeks of no updates. The kerneltrap interview generated a lot
of new traffic (Hi!) but the timing wasn't so great, it's the end of the school semester meaning I've been studying
like crazy for the last two weeks. A few exams, finishing up a bunch of applications and writing up a paper on
network management in Ad-hoc environment. Fun subject if you have the time for it (if you're interested btw, grab
it here) which unfortunately was absolutely not the case. But
anyway I believe I've survived most of it and managed to hack together some stuff for project vga in the progress.

I've talked about the problems with open OCD getting to recognize my programmer correctly before and noted that
it had some issues regarding parsing and playing XSVF files correctly. I was about to get into some serious
retooling of open OCD when one of the developers said to another on the mailing list;

Also, taking into account the main purpose of OpenOCD (ARM debugging),
if statemove works with ARM cores, then everything is just fine.

I might be taking things a little out of context here but it's what motivated me to develop a custom XSVF
parser for project vga. Since I'm using a standard FT2232D chip it should also work without too much effort on
other programmers using this chip, which means Amontec JTAGkey programmers and the like. Right now though it's
identifying the programmer by its location id, a specific string which is written in the EEPROM of the FTDI. This
can be easily changed however. Because I had to understand what was going on in the first place I read up about
JTAG and the FTDI commands to control the MPSSE controller. Note that I'm not using the JTAG libraries provided by
FTDI but sending raw commands directly.

You can grab an early copy of the XSVF Parser here which should compile under cygwin on little endian
machines. I haven't done any testing on anything else but windows yet, however I've been told that with the proper
drivers and commenting the inclusion of the windows.h header it compiles on linux and after some slight changes
it talks to an Amontec programmer as predicted. If you want to compile it get the latest FTDI drivers and libraries
here (it's the closed source once, basically because they're
quite a bit faster than the open source one I've been told - it shouldn't be too hard to support the open source
one as well) and extract those files in the folder with the xsvfparser. Actual command line details are explained
in the source file.

It isn't quite done yet since my main problem at the moment is getting the runtest to work properly. The
documentation has a few things to say about runtest;

Defines the amount of time (in microseconds) the device
should sit in the Run-Test/Idle state after each visit to
the SDR state when the current XENDDR state is IDLE (see
the XENDDR command below). The initial XRUNTEST time is
zero microseconds.
Note: For XSVF containing XRUNTEST commands applied to
Xilinx FPGAs, the time parameter must be interpreted as
the minimum number of TCK pulses issued within the
Run-Test/Idle state after each visit to the SDR state.

Ok, fair enough, but the idea was that the parser didn't have to know about whatever was going on in the file
or JTAG chain and that the XSVF contained all details. There's no way of knowing if we're supposed to clock or
not. And if we assume all commands require clocking, will it cause problems on the CPLD? Both an FPGA and a CPLD
are in the chain, so we have to find some middle ground. Obviously, since we're actually flashing data into the
CPLD I favor not clocking since all commands I care about (that is, flashing data) are supposed to be for the CPLD.
However, what am I supposed to do with the XCF? But wait, it gets even better, what does it say in the details
regarding SDR commands?

If the TDO value does not match TDOExpected, perform
the exception-handling sequence described in the XC9500
programming algorithm section. [...]
If the last XRUNTEST time is zero, then go to XENDDR
state. Otherwise, go to the Run_Test/Idle state and wait
for the XRUNTEST time.

What exactly is this exception-handling sequence? I haven't found a clear description of it anywhere. Great.
Also, the CPLD will obviously perform some kind of action during the period we're waiting, but we've already
clocked out the data at this point. So in this scenario the TDO value will pretty much always not match
what we're looking for the first time, which makes the exception-handling sequence even more important. Oh, and
bonus points for the people who spot the contradiction. Is there a situation where we have to wait for the runtest
time according to one description and not go to it according to the other? (hint: YES. And in that case, which
state should we go to or stay in? I haven't got a clue)

So that's about it for where we are at this point. It can already execute correctly some easy files like
fetching all device IDs which is more than openOCD could accomplish and gets pretty far with the somewhat more
complex ones, but fails at properly implementing the runtest. In less than 3 weeks I'm having an audit about the
project at my university so far, and the idea is to get at least something flashed into the devices by then. The
week after that I'll be most likely presenting the prototype with some background info at FOSDEM in Brussels in
the X.org devRoom. If you feel like dropping by, see you then!

Update 30 Jan:
I found out about xapp058 for
which is also some example code available
but alas, it only confuses more on certain points. I still haven't figured out what the exact byte (and bit) order
is in the XSVF files and everybody seems to just do something. The example code helps though. I do think I'm getting close;

tdoMask: 0x000003
tdoCache: 0x000008
tdoMatch: 0x000001

It looks like I'm just a few bits off, however, figuring out where the problem exists in the code is proving
to be quite a challenge. Xapp058 has a few nice diagrams explaining the earlier runtest problem, but also
introduces a new one; the first thing it does in Step 3 of Figure 9 (page 13) is shift out a single bit of data, without
sampling TDO. I'm almost certain that this must be wrong; if I'd do that, the code would already fail when checking
the device ID earlier. Also, the examples in xapp503 contradict this too. It's still suspicious though.

I uploaded the latest version of the parser (saved it over the old one, you can get it here) and it's a bit
of a mess at this point due to all the debugging statements, so sorry about that. You can find the output here, when executing this
xsvf which is supposed to do a blank check of the CPLD. A final note; I limited the number of xrepeats because
it got annoying to see the same error 32 times. I periodically check if it might help to do it 32 times but so
far it didn't matter at all.

Oh, and before I forget; xapp058 defines the XC9500 exception procedure so I implemented that as well. So far
though it didn't really help mostly because maybe I'm still shifting in incorrect data somewhere somehow. I
suspect this problem only showed up by now because this is the first statement where the data shifted in has
different remaining bits from the first (or last) bytes that have to be shifted in. Or something like that. I'll
keep on trying stuff out. I'm suspecting that the '8' I'm seeing is in fact my own bit I shifted in - meaning the
CPLD is in bypass and not doing what it's supposed to do. Then again, maybe it's meant to be in bypass but should
give a bit back as well, making the output '9'. That would fit the mask and explain some of the behaviour I saw
when I was definitely shifting out incorrect bits. But it wouldn't explain why I'm shifting out that 1 bit in the
first place. Argh.

Second update today
Found the culprit, I flushed the buffer when it was full, intended for when data was going to the Instructions
Register and the buffer size wasn't set yet (thus the default) it would flush and continue. There was an off-by-one
in there however causing it to flush the data early sometimes which under certain circumstances caused errors.
Really odd, but should do the trick now. This also means the code is probably bug-free enough to start programming
the CPLD with actual code! I'll continue tonight however with further testing and trying to get it to work for the
XCF as well, which needs some other things (like tck clocking in runtest) and seems to fail after the first bank is
tested. No idea yet why. See the error report here.

Update 31 Jan:
With some little effort getting familiar with ISE Webpack I wrote a little timer which counts up to some insanely
large number on every clock, which should result in a nice blinking LED roughly once a second. Turned out the
connection for the second LED connected to the CPLD is broken, something easily fixed if you have a soldering
station handy. Which I don't have right now. So two-led-magic will have to wait. The code used is here, the mapping
of the pins is here, and the reasons all PCI pins are already defined is because I've also been playing with
Ben Jackson's code but that part isn't working yet. Now, without further ado;

A little test app flashed in the CPLD

Exciting, isn't it? Unfortunately the system is unwilling to boot up with the card plugged in, I suspect it's
because I'm not giving it some proper data when it's trying to initialise the card. The reason is that I've done
some lengthy checking for shortcuts which might've been caused due to soldering the components on the board but
couldn't find any. Haven't verified yet if all CPLD pins are actually connected to the wires, that might cause
some corrupt data or something. But at least it should start the system up without using and registering my card,
but it refuses. So sorting that out, as well as trying to get the XCF PROM programmed properly (still failing for
reasons unknown - probably still a few bugs in the code) will keep me busy for the next days or so. On a final
note, this is how the chain looks like in iMPACT, just to show you that I don't have to worry anywhere which
device is being programmed or how my chain looks like (contrary to openOCD) because iMPACT takes care of those
details;