Tuesday, February 9, 2016

Solid progress debugging virtual 1442 card reader/punch function


Testing 1442 reader/punch logic

Imagine my surprise to find that I had not instantiated a module to respond to XIO Control, which explains perfectly why my adapter logic didn't trigger on the attempt to read a card. Doh. Software reads using an XIO Control with a modifier bit to signal Start Read. I added that in along with some good diagnostics.

I found the spot to jumper off the recognition of XIOs to area code 2, which is the 1442 device. Gate A, compartment C1, card F3, pin D06 will be jumpered to ground, pin D08. This keeps the Area 2 signal false at all times. That leaves my adapter free to respond to any XIOs aimed at the virtual card reader. Later I will replace the simple jumper with a nice SPST switch and label it "Disable 1442 support".

blue jumper disables 1442 adapter inside 1130
I was thinking about how to set up the dual mode for my 1442 logic, allowing it to capture the cards read and punched on a real 1442 as a mirror device or to replace a real 1442 with a virtual device. I think I have a sound strategy, which I will apply once the current logic, purely virtual, is working right. When in mirror mode, the output punch file is the only file used and will contain any card columns read on the real 1442 (plus any columns subsequently punched in the same card image).

I found a comment somebody posted on an EDA board that the too many bits false error I have been hitting can be fixed by setting the Xilinx ISE tool to windows 7 compatibility mode. I did this and so far no more errors, which were happening almost every other time I tried to build a new bitstream. Crossing my fingers this works.

I have my new Artix 7 75T chip based board but will continue my testing with the current Spartan 6 16C based board since I believe I have to switch over to the Vivado design suite from ISE in order to build logic for the Artix. That brings a whole set of possible problems that I don't want to trigger right now. Since my current logic is less than half the size of the Spartan 6 board, I don't have to make a move right away.

New board, FPGA more than 5X capacity of old board
My first test with the XIO Control included still didn't fire. I was able to test my jumper - without the jumper, an XIO Sense Device receives a DSW of 0x2001 which has the not ready bit plus another condition. With the jumper installed, the DSW is 0x0000 which means the inboard 1442 adapter is disabled as intended.

I dug into the logic and found that my trigger to spot when an XIO is executing on behalf of the card reader took the area code from my UCW table, but I had incorrectly initialized that to 00011, area code 3, instead of area code 2, 00010. The fix was made and I got back out to test once the bitstream was generated. Still no sign of the false errors now that the Xilinx ISE toolchain is in Win7 compatibility mode!

Now my logic saw and responded to the XIO Control, correctly saw that bit 13 was on, indicating Start Read, but my logic in the Python program failed to see it properly. I mistook it for an invalid Control code. I proceeded to correct a series of Python code flaws hoping to finally get to the point where I pushed down the card image to the pre-read buffer and began triggering fpga logic again.

I confirm that my write logic is pushing 80 words of data in 8 transactions, loading the pre-read buffer. What should happen, but does not, is the last push of the data should move the 'feed cycle' FSM forward but I see it sitting in the idle state. I am now narrowing my look at the FPGA logic that handles the push of the pre-read words and the feed cycle FSM.

I thought I knew what was wrong but I still am not seeing the 1442 kick off its feed cycle after the data is pushed down to the pre-read buffer. I am going to need plenty of diagnostics as well as to pore over the logic. With only 7 LEDS (plus eight bits I could display on the GUI), it may take many cycles picking sets of signals until I find the most informative set.

After more progress, I ended the evening with the feed cycle moved to its armed state and waiting for the write process that loaded the pre-read buffer to signal completion. Somehow that next step is not take. Now I now what to zoom in and watch.

Monday, February 8, 2016

Testing underway for 1442 function, plus preparing my replica 1627 plotter for attachment


Implementing and testing virtual 1442 card reader/punch

I finished the logic but keep flirting with yet another flaw in the Xilinx ISE toolchain. I get phantom errors in bitgen that I have too many bits for FDRI, which will go away, usually, if you do a Project Clean, restart the toolchain and run the generate again. Discussed quite a bit on various internet boards, as are the several other highly annoying flaws that waste design time.

Once I have a good generate I will fire up the system for the first test of the 1442 function. This will be more challenging from a testbed standpoint because it takes more hand toggled code to drive a 1442 properly. There are interrupts on level 0 for every column to which I must quickly respond with the XIO Read, as well as on level 4 for the completion of the card. I think I am ready.

I powered up and ran a test. It didn't work properly but that is not surprising because my hand code is still funky. I found some errors in my IOCC formats, for example. It will be hard to single step through the code to check it. With a 1442, there is very tight timing required to issue the XIO Read after each int on level 0.

If I tried to run the code in single instruction mode, a real 1442 reader would throw an error as the Read wasn't done fast enough. My virtual reader won't throw an error but it inexorably advanced through the columns triggering IL0 even if the Read didn't happen, so if I ran in SI mode it would not capture any card data.

I saw no response to the XIO Control with the bits to command a Start Read. I looked through the FPGA logic and found some code I thought was cleverly handling the case when the real 1442 adapter is live, but it wasn't. Worse, I forgot to tie down the 1442 adapter so that it was trying to respond to the XIO. I ran out of time for testing today but know what I need to do tomorrow - some diagnostic indications in the fpga and Python to help track what is occurring, once I have the jumper in place to disable the 1130's 1442 circuitry.

Implementing physical plotter (1627 equivalent)

I began by testing my interface electronics for the plotter, intended to allow the Strobe model 100 to act the same as a 1627. Something was not working correctly, however the movement buttons themselves work properly. This suggested the level shifter chip, since that is the main unit that sits between the input connector and the remaining circuitry that seems to be working properly. It was time to do some diagnostics.

This turned out to be solely an issue of bad connectors, a weakness of some of my project work. I was able to remove the connectors and validated I can drive the plotter left, right, up, and down as well lift or lower the pen to the paper. The plotter will be one of the devices that has its signals driven through a high speed link to another FPGA board which

I believe I have correct logic in the fpga matching the inboard adapter that IBM would install in 1130 systems if they came with a plotter. Mine does not, but the SAC Interface box will stand in for that logic. This will be the first thing I connect once my 1442 adapter is working solidly.

Sunday, February 7, 2016

Fought space limit in FPGA and almost back to testing 1442


The new FPGA board is due to arrive Monday afternoon which is pretty good for a shipment from Germany for an item I just ordered and from a small operator, Ztex, who does not have a big warehouse and shipping department.

I began commenting out large chunks of my logic (1053 code, 1132 code, 1403 code) but the number of LUTs seems to be remaining at the same level. Something seems to be wrong. I might have another Xilinx toolchain failure that is falsely reporting the out of space problem. I will hack some more out (well, comment out everything) and see if this is a problem caused by ISE.

I commented out the two SPI links, all the CRC checking and still am above 100% on LUTs. Something is wrong, but I don't yet know which of three possibilities is the cause. It could be some code I added to the 1442 support which somehow implied a huge number of LUTs, it could be that my logic legitimately needs more than 10,000 LUTs and had been under the limit because of signal trimming when portions weren't completed yet,  or it is another of the bugs that crop up in ISE which cause bizarre behavior

If the problem is an ISE defect, this will go away since I have to upgrade to Xilinx Vivado to make use of the Artix chip. If the problem is that I legitimately need that many LUTs, then my much larger chip on the new board will give me the breathing room I need. The only case that is bad is the one where I coded something that implies a huge LUT count, but I am not noticing the error I made.

I think the only way to get to the bottom of this is to comment out the 1442 code and see what happens. If there is not a huge drop in LUT count, then I will comment out some of the latest changes to the transactional engine. Hopefully something will drive a major drop in LUT count.

When I commented out one process that sets a word from the card buffer, based on the index of the current column being processed, the size plummeted to 18% of LUTs used. I uncommented the process and did another synthesis just to confirm whether this was the problem. Indeed, the simple looking code drove me up to 109% of LUT capacity from 18% without it.

It appears that this is strictly due to the logic to mux 16 bits per column times 80 columns down to the single 16 bits needed for the column read. Since I am light on use of distributed and block RAM, I will convert the buffers into a memory in order to free up LUTs. The challenge here is that the code to load the pre-read buffer and dump the pre-punch buffer, which had been implemented to dump 10 columns in a single cycle, will now take 20-30 cycles instead of one. I may need to adjust the short packet timeout to accommodate this extra delay.

With this change, I can remove ALL the commented sections and get back to testing the 1442 function. I was able to get all the way to bit generation with no space issue but there was an issue with how I used the block ram that was only flagged during bit generation. The software inferred a 9K block RAM component for each buffer, but has a flaw that fails to initialize the contents. Xilinx flaw with 9K ramI don't need any initial contents but this stops the creation of my bit file. Most significantly, only 37% of LUTs and 3% of block RAM required so my change rebalanced the chip usage nicely.

Implementing and testing 1442 reader/punch

I converted the two 80 card column buffers from LUTs to block RAM, since I had plenty of the latter but was short on the former. The dump and load of the buffer becomes a bit more complicated as I had to watch where the various control signals are driven and have a process to step through ten sequential locations in the buffer.

Once I resolve the Xilinx ISE issue with 9K block RAM initialization, I should have a good bitstream to load into the fpga. I think the solution is to use the block RAM generator rather than having the ISE recognize my VHDL and convert it to the component.

Friday, February 5, 2016

Need to upgrade to bigger FPGA to continue developing SAC Interface Unit


Implementing and testing the virtual 1442 function

My research into the 1442 adapter highlighted that a XIO Control with Stacker Select bit set will NOT cause an operation complete interrupt. Therefore, the only handling I need when a SS is issued is for the Python program to detect that and cause the punch buffer from the fpga to be written into the alternate file (if open). This eliminates the need to force op end interrupts by a transaction from the PC; it can be handled purely locally in the fpga.

After some discussions with Peter Vaughan of TNMoC (The National Museum of Computing in Bletchley, UK), it seems there is value in also supporting a 1442 mirror mode, capturing card images of physical cards as they are read or punched on a real 1442. The logic to support this is relatively close to the logic for the virtual function.

From a design standpoint, I need to add a switch to the 1130 to enable or disable its 1442 adapter and I need some means to tell the fpga to operate as a mirror or a virtual adapter. I can send a transaction from the Python code that tells the fpga which mode it will assume.

In the Python program, I need some logic to cause the first card to feed, when a new file was opened for reading and/or punching, when the program issues a Start Punch. On a real 1442, readying the device with cards in the hopper causes one card to feed into the pre-read station, but nothing is yet in the pre-punch area. The 1442 adapter logic will force a feed cycle on the Start Punch if this is so, advancing the card from pre-read to pre-punch in order to begin punching.

Hopper empty condition turns the device Not Ready, although a last card may be in the pre-read station and the next to last may be in the pre-punch station. Pushing the Start button on the read causes it to go ready and allow one more Start Read but has also set the Last Card bit in the DSW.

As I made the refinements to the 1442 logic that I had mentioned yesterday, the unthinkable happened. I ran out of space on the fpga! Too many LUTs needed. I suspect that some of my registers and buffers could be placed into block ram, freeing up a decent number of LUTs, but from this point I am going to have to start optimizing and making choices. Drat! This could slow me down.

In lieu of all the juggling and optimization, or removal of desired functions, I just bought a replacement ztex board, with the same 100 I/O pins but a much larger and faster Artix 7 FPGA on board. I moved from the 2.01 board with a XC6LX16 chip to to the 2.13c board with the XC7A75T fpga chip. I also get a huge onboard RAM as a bonus. It should arrive in about a week, meanwhile I can comment out some portions of the design to free up LUTs for near term testing.

Thursday, February 4, 2016

More work on virtual 1442 reader/punch functionality


Implementing virtual 1442 card reader/punch

I rolled in the logic to handle the interrupt request and reset, plus the logic to latch in each column for the XIO Read or update the punch buffer for each column after the XIO Write. The last bit to add was the logic to pretend that an XIO Init Read was issued, so that the Python program can extract the updated punch buffer at the end of a read/feed/punch cycle.

I did a quick bit of testing and discovered a need to refine the overall logic between the fpga and pc. The problem is in handling a feed cycle, which should copy the pre-read buffer to the pre-punch buffer and signal an operation complete. Another problem was is in triggering an operation complete when a stacker select is processed.

Not totally completed with the rework, at least in the time available today to work on the system.
At least I have started into testing and hammering this device function into operation. It needs a jumper to prevent the 1442 inboard electronics in the 1130 from recognizing XIO instructions, allowing the FPGA to handle them instead.

Tuesday, February 2, 2016

Working on both virtual and real 1442 card reader/punch units


I built up more of the Bondic material around the punch wheels in preparation for rounding it off to just below the wheel circumference. Once prepped like that, I can make a slurry of grit and Bondic, spread it thinly on the repaired section and harden it with the UV light.

I am going to need a very good jig to hold the wheel, turn it through the arc where the wheel is damaged, and to guide the grinding/polishing tool to the precise radius I want. I need to design this and then build it.


Implementing virtual 1442 card reader/punch

I have a big decision point about how I will implement the 1442 support. There are two possibilities:
  1. a virtual device using files on the PC
  2. a mirror device that grabs card images read or punched on the real 1442
The 1130 system has the adapter installed for my 1442, so that it will respond to XIO instructions and respond with status. If it is doing that, all I can do is to mirror what it happening with my logic, grabbing the data as it flies by. In order to take choice one I would have to tie down the line that signals the adapter that an XIO is addressed to the 1442 address (area code 2).  Mirroring is easier but less useful since I still have problems getting the 1442 back in operation.

Major reasons to implement a mirror device using the real 1442:
  • Ability to read real decks of cards I own
  • Ability to punch out real cards
Major reasons to implement a virtual 1442 device and disable the real one:
  • Can move virtual decks between the real 1130 and the simulator on a PC
  • Can move ahead before I get the physical 1442 working
The choice gets easier when you consider the following:
  • I have a Documation reader that can read cards in and use them on the PC
  • I have an 029 keypunch with a modification to let me punch real cards from PC files
The two facts above eliminate the major advantages of a mirror device implementation. Therefore, I will build this out as a purely virtual 1442 reader/punch and stick a jumper into the 1130 to tie down the 1442 adapter so it does not respond to its address. That allows my logic in the FPGA to step in and respond to 1442 commands.

I have implemented the logic in the FPGA that allows the Python program to push down a card image into the pre-read buffer, wait until the punch or read operation is complete and then fetch the punch buffer contents. This is a feed cycle with or without the read/punch.

The Python program feeds the card images by reading them from an input file, and will add the card images coming out of the punch buffer to an output file, if it is opened. The way I handle stacker select is a bit funky, but it was easiest considering that using the alternate stacker is somewhat rare.

A SS XIO Control operation is issued after one receives the operation complete interrupt for the prior XIO Control start read, start punch or feed operation, but before card travel has completed. In my flow, I have already written the card image to the punch file by the time I get the SS request. It is easiest for now to just punch a special record afterwards that indicates the prior card image goes in the alternate stacker. I can use the Deckview utility to move those card images to their own file, as a post-processing step, if it is ever needed.

There is an alternative I see, but it adds some complexity including the need to maintain separate output files for both stackers, update the GUI for both file open buttons, and so forth. To make this work, I would save the position of the punch output file ('tell' operation on the file) before writing each punch output image. If a subsequently got a SS command, I would back up the main output file to its previous point, erasing the card image I added. I then write the saved card image to the alternate output file.

The remaining implementation details are in the FPGA, including:
  • moving the pre-read buffer contents to the pre-punch buffer at operation complete
  • a read FSM to fire off 80 IL0 interrupts, wait for the XIO Read and latch the column data
  • a write FSM to set up the column data, fire off 80 IL0 interrupts, and wait for the XIO Write
  • a master FSM to spot pre-read loading, trigger the read or write FSMs and send fake XIO IR
  • make sure the IL0 and IL4 state flipflops are modified to suit the new approach
At lunchtime, I built the read and write FSMs, along with the master FSM. The read and write FSMs also enforce timing simulation to deliver approximately the real throughput of a 1442 model 7. That means delays before beginning the IL0 interrupts for columns and then the proper timing between columns to match the 400cpm of reading and 120 cpm of punching.

I didn't have anything complete enough to test today so I continued developing logic and refining the Python side until this is complete enough to begin testing.

Monday, February 1, 2016

Virtual 2501 card reader functionality tested and working well, building out 1442 implementation


Testing virtual 2501 card reader

I fired up the system and tested the 2501 card reader function by toggling in some hand code to issue the XIO Init Read to do reading, an interrupt handler that grabbed the DSW along with a reset, paused, then went back to the mainline. My mainline is the XIO read plus a pause and loopback, letting me examine the buffer contents after each read.

I used a few card decks from the 1130 simulator as the data to read and check. When I first fired up my hand program, I saw it issue the XIO but there was no sign that my fpga nor the Python program was active processing it. I looked over the fpga first to be sure it was capturing the XIO IR and the Python program, but also stuck in some diagnostic LEDs and messages to help. I then discovered that I had forgotten to click the checkbox to activate the virtual 2501 support. I went back out to test again and found a couple of minor flaws in the Python code that were introduced because I collapsed several transactions (last XIO function, WCA address) into one.

I discovered that my unicode oriented read of 029 format files (IBM 1130 ascii files of card images) fails on Ubuntu Linux but works on Windows. I will need to work on this but initially I will just used native 1130 simulator (Binary) format files.

My testing worked great for the file I entered, until I ran into the end of the deck when the card reader should go 'not ready' unless the 'last card' checkbox is on. My primitive hand code does not check for not ready, but just ssues another XIO Init Read even though the file is done, My python code doesn't watch for this and attempts to read the next image from the closed file, causing an error. I can protect against this in the Python code.

A real reader acts the same way when the hopper empties. It signals not ready, then if the operator pushes the start button with no new cards in the hopper, it goes ready in last card mode, so that the next XIO Init Read will read the final card and then the operation complete interrupt also has the 'last card' bit set in the DSW to tell the software that this is end of file rather than a temporary case where more cards have to be loaded in the hopper.

I will fix up the Python code then step through the card images in my hand code on the 1130, seeing that it behaves properly for both the last card sequence and the 'out of cards' not ready case. If this is fixed, the only issue is converting 029 format unicode files to the native binary format as I open such files.

I still had a flaw in how I deal with my incorrect code that is issuing XIO Init Read on the virtual 2501 when it is not ready. The solution is in the FPGA, where I won't record the last XIO Function Code if either Not Ready or Busy is on in the DSW. The Python code won't see any XIO in that case, until it loads a new file and sets the DSW back to ready (turning off Not Ready bit).

The code I wrote to handle the Unicode ASCII (needed for two special characters on card images that are not part of the 8 bit ASCII character set) used the windows generic encoding 'mbcs' but Unix and Linux have no default. I changed the code to explicitly request 'UTF-8'. Testing showed this worked perfectly.

I ran multiple decks through the virtual card reader, including a mix of binary and Unicode ASCII, with everything working as expected. The last card image of each file will be left 'in the reader' with the reader not ready, unless the 'last card' checkbox was selected which allows the last card to also be read. The DSW showed last card or not ready exactly as would occur with a real 2501.

At a later time, I will test the boot operation on the virtual 2501. This will read one card image in the special program load mode, stuck the 80 columns in memory starting at location 0, then trigger my pseudo-program-load sequence.

Building virtual 1442 functionality

I jumped into modifying and building the logic for the 1442 reader/punch since a few aspects of that design caught my attention. The PC side is pretty clean, while the FPGA side is a bit more complex mainly because of looping FSMs emitting column by column interrupts and the timing modeling for feeding and other operations.

The PC will watch for XIO instructions and respond to XIO Control and XIO Init Read (a fake operation that the programmer should never execute for a 1442). Any of the XIO controls will cause a feed cycle, which involves pushing down one card image from the PC file. I decided that users must open a file of 'blank cards' if they are punching, otherwise there are data cards in the file.

The FPGA will see the card pushed, start emitting column interrupts at the proper pace, handle XIO Read or XIO Write within the fpga by feeding or updating the two card buffers, and claim to have seen an XIO Init Read when the last column of read or punch is processed and the elapsed time matches the performance of a 1442 model 7.

The fpga will hold off on the operation complete interrupt (IL4) until it sees that the PC has fetched the last of the punch buffer, then it triggers the interrupt and clears it after the XIO Sense DSW with Reset bit is processed.

The PC program sees the XIO Init Read code and fetches the punch buffer contents. If an output file is open on the PC, it writes that image to the end of the file. In either case it goes back to polling for the next XIO Control operation.