Running Off Into the Weeds

I always wondered why things take so long. Now I know.

For the past month, I was working on a Python version of the XSTOOLs software. I wanted an easy route to cross-platform capabilities for Windows, linux and OSX, and interpreted Python provides that. And not needing a compiler makes it easier for my customers to modify the software for their systems.

I got most of the fundamental functions of the software working (talking to the FPGA JTAG port over USB, downloading bitstreams, etc.), so I thought I could break off of it for a while and take care of other unfinished business. (Which means I'll have to re-learn everything when I come back to it in six months.) My major to-do is to complete the Spartan-6 version of the XuLA board, so I opened that back up on Saturday morning.

The first thing I did was to start another Spartan-6 project to test some more of the board functions. But that requires porting over some of the design library for the original XuLA board. I looked in my local XuLA repository and I wasn't very happy with how it was organized: the FPGA design library was in it's own separate repo on github and the PCB design files were in another repo over on Solderpad. And the firmware for the board was in a couple of separate repos that weren't even on public servers but were only available as static zip files. Finally, there were some files that weren't even under any version control at all. I really wanted the XuLA stuff all integrated into a single repo like I did with the StickIt! motherboard and modules.

It's at this point I should have recognized that the wheels were leaving the highway. I really didn't need to clean-up the XuLa repos in order to build a few test designs for the new FPGA board, but once I got pointed that way I couldn't swerve back to my original heading.

The first thing I wanted to do was get all the separate git repos under one master repo, but I didn't want to lose all the history in each repo. I did a search for "integrating two git repositories" and managed to find this relatively simple procedure for doing just that. But it requires that the individual repos should have all their changes committed, and that wasn't the case for me: I had lots of uncommitted FPGA files for ideas I had been testing.

So I had three possible ways to go: 1) throw away the changes; 2) save the changes somewhere, commit the repos without them, and restore the changes later to the new integrated repo; or 3) check the modifications into the repos and then integrate them. Option #1 wastes the time and effort I put into the modifications. Option #2 is messy and just delays the eventual integration of the code modifications. Option #3 is the most direct but comes with its own problem: How do I know the changes are correct? Some of the modified files are in a central library, so they impact multiple FPGA designs. The changes have to be tested for each design before they're committed.

And here's where I took another detour and pushed even farther into the wilderness. I didn't really want to individually recompile all the FPGA designs using the Xilinx ISE GUI tools; I just wanted to start a makefile and let it all happen automatically. I had written a set of makefile rules for compiling FPGA bitstreams, but it was always a pain in the ass to update it so it would work for each new release of the Xilinx software. I decided to look for a canned solution to this batch compilation problem. I found four possible techniques covered in this Xcell journal article, and I chose the tcl-based method. I could use ISE to generate a tcl file containing all the tool invocations and their settings for each of my FPGA projects. Then I could kick-off the tcl file for each project by adding this new rule to the makefile:

%.cfg: %.tcl
    xtclsh $*.tcl rebuild_project

Now I had to manually open each FPGA project with ISE to generate its tcl file, so you might ask why didn't I just run the compiler and get all the bitstream files right there. You're right, I could have done that, but then I would have to do it all over again each time I changed the design files. I figured it was better to take the pain once and create all the tcl files so I could do push-button compiles of the entire batch from then on.

Once I had the tcl file for a single trial project, I started the makefile and it completed without a hitch. Oh happy day! But then I looked closer and saw that no bitstream file had been built; the FPGA project had gone through logic synthesis, translation, mapping, place-and-route and then stopped. So I looked in the tcl file and found this particular line:

set task "Implement Design"

This tells the tools to take the compilation all the way through place-and-route, but no further. What I needed to get bitstreams generated was:

set task "Generate Programming File"

I looked all over the ISE menus, but I never could a way to change how this portion of the tcl file was generated. So I added some more stuff to the makefile rules to substitute "Generate Programming File" in place of the "Implement Design" option in the tcl:

%.cfg: %.tcl
    perl -p -e "s/set task \"Implement Design\"/set task \"Generate Programming File\"/" $*.tcl > $*-tmp1.tcl
    xtclsh $*-tmp1.tcl rebuild_project
    -$(RM) $*-tmp1.tcl

The new makefile rule successfully generated the bitstream for my trial FPGA design, so I figured I was ready to do the whole bunch. After creating all the tcl files, I initiated the main makefile and it bombed on every project, even the trial design I had used to test it.

So I looked at the tcl files to see if anything strange was in happening there, and they had changed: the process settings that control how the FPGA compiler works were all gone. This meant the compiler would use the default settings, but that wouldn't work for my projects because I had a few quirks such as using the JTAG clock for starting-up the circuitry rather than the CCLK.

I figured I had unintentionally flipped a software switch in the ISE tools before generating the tcl files, but none of the available options would restore the process settings. So I did the next thing everyone learns to do and rebooted the PC. Still no luck. Then I upgraded my ISE software from version 13.1 to 13.4. Still nothing. At this point I'm figuring there's some flag in the registry that's stuck in a setting that prevents me from ever getting what I want.

So then I committed the ultimate act of desperation: I submitted a question about my problem to the Xilinx user forum. In my experience, you get a useful answer from the forum about as often as we elect a new Pope. And I wasn't disappointed: it's been four days and still no replies from anybody.

While waiting for a reply, I realized I had the ISE tools installed on my laptop. Maybe I could generate the tcl file with the process options there and then transfer it to my main PC. Unfortunately, I had version 11 of the ISE tools on the laptop, so I had to re-create one of my projects there (ISE 11 would not open a project built by ISE 13) and then generate the tcl file. And this one had the process options I needed!

I took the file back to my main PC and extracted the process options into a separate file. At that point I could have just included the file into the tcl file for each FPGA design, but what's the fun in that? Instead, I stored the process options file at the top of the project directory tree and then modified the makefile rules to include it into the tcl file for each project:

%.cfg: %.tcl
    perl -p -e "s/set task \"Implement Design\"/set task \"Generate Programming File\"/" $*.tcl > $*-tmp1.tcl
    perl -p -e 's|(   puts "\\$$myScript. setting process properties..."\n)|$$1   source "../../process_properties.tcl"|' $*-tmp1.tcl > $*-tmp2.tcl
    xtclsh $*-tmp2.tcl rebuild_project
    -$(RM) $*-tmp1.tcl $*-tmp2.tcl
Don't bother trying to understand this - with all the shell escapes and special characters for make and perl, even I don't remember why it works anymore. But it did work and all the projects successfully compiled into their bitstreams.

Now I was finally ready to commit to the repo. While working with the tcl files, I realized there were a lot of files that didn't need to be in the repo. Rather than pick through the project directories and find the unneeded files, I just ripped everything out of the repo index with this:

find . -exec git rm --cached {} \;

Don't forget to use the --cached option or else your working files will get deleted as well. (Yeah, I did that.) Once everything was removed, I went back and added just the files I needed - VHDL files (.vhd), project files (.xise), constraint files (.ucf) and documentation files (.pod) - using commands like this:

find . -iname *.vhd -exec git add {} \;

Things were going fine until I tried to add the .tcl files. The find command only detected a single tcl file in the top-level directory; it was missing all the others in the project directories. To check my sanity, I tested for the existence of the tcl files like this:

ls -l -R | egrep "\.tcl$"

Sure enough, an additional seventeen tcl files were found. Now, the find command has been around since I was a baby (OK, not that long, but it's been around since I was able to make babies), so I doubted there was a bug in it. But I couldn't see how I was misapplying it, either. Eventually, I just threw up my hands and added the tcl files manually, one-by-one. This crap was taking far too long.

After committing all the changes to the FPGA design repo, I integrated it into the master XuLA repo without any problems. I did the same thing for the pcb and microcontroller firmware repos (which weren't in nearly as bad a shape as the FPGA stuff). And then I added the unversioned files for things like the XuLA manual. The final result was an integrated, all-inclusive XuLA repository hosted on Github. Truly a marvel to behold!

Now, what was it I was going to do....

Taxonomy upgrade extras:

Comments

If you want a Python option for building Xilinx ISE projects, see Guenter Dannoritzer's Python scripts, which generate the underling tcl, but the OO interface in Python is better than generating tcl directly, http://www.myhdl.org/doku.php/projects:ise_py.  
 
An example, you can quickly and as easily create an ISE project.  

--------------------------------------------------

# set up pin configuration for the FPGA
fpga = Fpga(path=ppath)
fpga.setPin('clk', 'P124')
fpga.setPin('srst', 'P8')
fpga.setPin('led<0>', 'P92')
fpga.setPin('led<1>', 'P93')
fpga.setPin('led<2>', 'P95')
fpga.setPin('led<3>', 'P96')
fpga.setPin('led<4>', 'P97')
fpga.setPin('led<5>', 'P98')
fpga.setPin('led<6>', 'P99')
fpga.setPin('led<7>', 'P100')
fpga.setDevice('spartan3', 'xc3s400', 'tq144', '-5')

imp = Xilinx(ppath, 'stroby')

imp.setFpga(fpga)
imp.addHdl((vfile))
imp.createTcl()
imp.run()
--------------------------------------------------
 
Note, this just a start, so use at your own risk and it is missing some key features.  Yet another rat hole to distract.
I have some modifications of the above here, https://bitbucket.org/cfelton/examples/src/tip/tools/_xilinx.py.
Thanks for the good posts,
Chris

Hi, Chris. Thanks for alerting me to this! I might try it for some internal development. I'd be a little worried about using it for projects I release to my customers since it diverges quite a bit from the standard Xilinx-ISE way of doing things.
I'm going to try and write a blog about some of the python tools for FPGA design. I have MyHdl, migen and now this. If you have any further pointers, I'd be glad for the information.
 

One of the benefits of the Python script is you can still distribute the TCL script to your customers.  You can use the Python script (or any other HLL) to manage the TCL script.  You don't have to write the TCL scripts by hand or export from ISE.  
I have found it useful because I can automate much more.  I can run a design through bunch of tests, automagically synthesize, P&R, test against the P&R.  Then download it do a device and test agains the hardware.  All this is done while I sleep :)

Thanks for the further info, Chris. I'll have to take a more detailed look at it.

O.M.Gs. That was painful. Painful because I know exactly how easily things can snowball pursuing tangent after tangent. Good for you that you are the boss otherwise you might have had a difficult conversation :)
Cheers
 

Hi, Tom. Yes, I did not have to explain this to my boss, but I did have to expose it to the hundred or so people who read my blog. I'm not sure if public embarrasment is better than private beratement.

Unquestionably believe that which you stated. Your favorite reason seemed to be on the net the simplest thing to be aware of.
I say to you, I definitely get irked while people think about
worries that they just do not know about. You managed to hit the nail upon the top and also defined out the whole thing
without having side effect , people could take a signal. Will probably be back to get more.

Thanks