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
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....
Comments
New Comment