whitequark changed the topic of #glasgow to: glasgow debug tool · code https://github.com/whitequark/Glasgow · logs https://freenode.irclog.whitequark.org/glasgow
<whitequark> ok
<whitequark> i need a taxonomy
<whitequark> spi-flash-25c is dumb
<whitequark> and spi-flash-avr even more so
<whitequark> what's important is that it operates on memory
_whitelogger has joined #glasgow
_whitelogger has joined #glasgow
<_whitenotifier> [whitequark/Glasgow] whitequark pushed 2 commits to master [+55/-44/±3] https://git.io/fhApf
<_whitenotifier> [whitequark/Glasgow] whitequark 8af62aa - software: remove explicit asyncio dependency.
<_whitenotifier> [whitequark/Glasgow] whitequark efb57fe - applet: invent a taxonomy and reorganize everything according to it.
* whitequark pokes marcan
<whitequark> think you can go over the various layout issues?
<whitequark> revC0 desperately needs design files exported
<whitequark> for one
<marcan> busy today, but ack
ali-as has joined #glasgow
<ali-as> whitequark, I share some of your pain with EJTAG.
<whitequark> ali-as: i also implemented the undocumented ejtag 1.x/2.0 hack required for broadcom silicon
<whitequark> that was horrifying
<ali-as> Hmm, what hack?
<whitequark> you have to enable DMAAcc, which is an undocumented mode that lets you directly read and write memory
<whitequark> to enable the rest of EJTAG
<whitequark> there's a bit that would cause the processor to fault each time you're trying to access drseg
<whitequark> er, dmseg
<whitequark> so you'd never actually, well, be able to feed it any instructions
<whitequark> now imo they should have kept DMAAcc and memory-mapped the CPU state or something
<whitequark> how fucking hard can it be
<ali-as> Interesting. Mid 2000's I modified HairyDairyMaid's router flasher to work with Broadcom SOCs.
<ali-as> That was a complete nightmare.
<ali-as> It was an early EJTAG version though, no DMA access.
<ali-as> 64bit CPU, about 40 address lines (I'm fuzzy on this).
<ali-as> I'd moved from STMicro ST20, which had an utterly glorious hardware debug system to EJTAG which seemed little more than a port to the CPU instruction scheduler.
<whitequark> no, my code is a descendant of HairyDairyMaid
<whitequark> that's the only place where DMAAcc is documented
<ali-as> Do the chips you are working with have a FASTLOAD register?
<ali-as> I never released my code btw. I was part of a small group of people interested in modifying sat boxes.
<whitequark> FASTDATA is in EJTAG and I think that exists
<whitequark> but it doesn't help a whole lot while introducing a huge amount of complexity
<whitequark> what I'm thinking about is well, using a small CPU on the FPGA to drive JTAG transactions
<whitequark> well I guess first I should add proper pipelining
<ali-as> There are some cool aspects of EJTAG I didn't really get while I was sweating blood over FASTLOAD.
<ali-as> At a time where you were lucky to push a TCK to 10MHz, the EJTAG port was specced at something silly like 40MHz.
<ali-as> And you only needed a small amount of memory to stop feeding the CPU instructions and just do data.
<ali-as> Of course the 40MHz spec didn't help at all, I was using a parallel port wiggler ;)
<ali-as> (reading), FASTDATA could be what I'm thinking of, but the openocd docs say it's 1 bit wide. What I remember is a register with PrAcc+Address+Data in one scan chain.
<ali-as> I made it work in one direction I think.
<ali-as> Halvar retweeted your EJTAG thread btw. Sorry to burst in mid like this is mid conversation ;) I've had people tell me I should look at Glasgow.
<whitequark> ali-as: ohhh that one
<whitequark> let me look up, i remember something like it
<whitequark> i may even be using it
<whitequark> ali-as: yeah, it's called "ALL"
<whitequark> register 0x0B
<ali-as> Hmm. Is it though. I've not touched this in 10 years. I swear I have PTSD trying to make that work, reading and burning was SO SLOW.
<ali-as> I looked into adding a CPLD to a MCU to speed up the protocol but never made anything happen.
<whitequark> yes, ALL is combined CONTROL+ADDRESS+DATA
<ali-as> I may be mis-remembering.
<whitequark> FASTDATA is basically a FIFO your code may be using through drseg
<whitequark> it's useful for something like piping printf() debug to a debugger
<whitequark> printf() output*
<ali-as> That sounds right.
<whitequark> oh, I see why it's not implemented, it's in EJTAG 2.6
<whitequark> wait, no, I'm wrong
<whitequark> FASTDATA saves you one CONTROL write to set PrAcc bit to 0
<whitequark> there is a separate mechanism called Fast Debug Channel in EJTAG 5
<whitequark> which is what I described above
<whitequark> the instruction for fast debug channel is called FDC
<ali-as> I was in a hell of a mess for months. I'd made a mistake with 64bit shifts (64bit support was undocumented and and a bit broken but the actual mistake was mine) and I had to have nops as half of the 64bit instruction.
<whitequark> amazing
<whitequark> no matter how bad you can make a claim about EJTAG i will believe you
<ali-as> Sorry no, support in the C compiler.
<ali-as> But there was no public code for 64bit EJTAG.
<whitequark> ahh
<whitequark> funnily enough, glasgow theoretically supports 64 bit EJTAG
<whitequark> all the parts are there
<whitequark> I just have nothing to test it on
<ali-as> Parts of EJTAG, including FASTDATA I ultimately think were broken in the chip, but that's probably Broadcoms Fault.
<ali-as> But then I never had a datasheet for the SoC because Broadcom don't do that.
<whitequark> FASTDATA or FDC?
<whitequark> broadcom seems to have some really weird concept of EJTAG
<ali-as> FASTDATA rings a bell.
<whitequark> ugh, let me pull the PCB out of the shit router pile i have
<whitequark> i went to the nearest pawn shop (or something like it) and bought their oldest, crappiest routers
<whitequark> in hope for jtag
<ali-as> My memory is that early EJTAG was just a hole in the instruction scheduler and someone says technically, in a turing complete proof kida way this is your debugger, enjoy.
<whitequark> it's mostly broadcom although i have found some truly bizarre SoCs
<whitequark> that's late EJTAG too.
<whitequark> all of EJTAG is like that.
<ali-as> At the time EJTAG had standards that had DMA, but this broadcom chip EJTAG version was pre DMA.
<whitequark> they actually removed DMA in the new EJTAG spec
<ali-as> I think I read that.
<whitequark> and in fact i have never found any EJTAG spec that would describe DMA
<whitequark> it's 1.x specs
<whitequark> which I don't have
<whitequark> I had to plunder register bit definitions from openocd
<ali-as> It's probably minimal silicon.
<ali-as> I 'discovered' the STM32F4 chips a few years ago, they will toggle at 80Mtoggles/second I thought fantastic, I can make the JTAG debugger of my dreams, but now JTAG locked out of most of the consumer hardware I'd want to access.
<whitequark> Glasgow is probably a JTAG debugger of your dreams :P
<ali-as> It actually probably is ;)
<whitequark> the level shifters are rated at... well let's say you will never make the FPGA fabric toggle that fast.
<whitequark> 200 MHz is doable.
<whitequark> 300 MHz, maaybe
<whitequark> really at this point your TAP isn't going to keep up for sure.
<ali-as> Wow.
<whitequark> right now I think fmax is around 10 MHz, but I simply never had a reason to push it higher.
<whitequark> I could make it go to at least 60 MHz with a few lines of changes.
<whitequark> 120 MHz with minimal work, 240 MHz with slightly more work.
<ali-as> I bought a 'DLC9' from ebay. It's not even an honest clone, it's a FTDI chip with a level shifter. Functional but fake.
<whitequark> ugh.
<whitequark> I hate the FTDI shit.
<ali-as> Yeah, yeah that.
<whitequark> I've implemented FTDI MPSSE in gateware.
<whitequark> Glasgow is supposed to be able to emulate FTDI chips.
<ali-as> Wow.
<whitequark> so far I found it more interesting *and* useful to implement applets that directly access the required interface though.
<whitequark> Glasgow has an integrated logic analyzer, so if you write an "accelerated JTAG" gateware and it breaks, you add a `--trace jtag.vcd` argument.
<whitequark> then you put that into PulseView
<whitequark> zero messing with wires.
<whitequark> the logic analyzer understands that JTAG is a synchronous interface, so if your gateware is trying to toggle too fast, it'll gate its clock until the LA buffers clear.
<whitequark> (some caveats apply)
<ali-as> WOW.
<whitequark> this means that when Glasgow is driving any synchronous interface as a master, you can directly observe the signals that the FPGA sees, with *zero* additional effort.
<ali-as> THAT IS AWESOME.
<whitequark> the logic analyzer is still rough at edges, e.g. if you have floating pins near the crossing point, it may quickly overload its buffer, and you can't stop that noise by stopping the clock, for example
<ali-as> The number of times I've had to hook up an oscilloscope to check what the REAL TDO response is.....
<whitequark> but it's quite usable
<whitequark> yep, no oscilloscopes
<ali-as> Everything abstracts JTAG protocol, everything.
<whitequark> you could even hook up signals from inside your gateware directly to the logic analyzer
<whitequark> like the FSM state
<whitequark> once I get some refactoring done, I want to make that fully automatic
<ali-as> Are there spare lines you can wire into other parts of the circuit?
<whitequark> so you get pin states, pin output enables, and state of your gateware, all with one command line argument
<whitequark> oh no, it's not structured like that.
<whitequark> you give it the set of signals you want to watch.
<whitequark> it converts that into a set of FIFOs, such that it uses block RAM more efficiently
<whitequark> for example, it also watches all the commands that are read from USB, and responses to them.
<whitequark> often, 1 USB command can produce 1000s of toggles on data lines.
<whitequark> and you don't want to share your FIFO depth between that.
<whitequark> so, it has shallow buffers for FIFOs, and deep buffers for data lines.
<whitequark> also, it does on-the-fly compression.
<whitequark> if nothing is toggling, there will be no data output on the logic analyzer pipe.
<whitequark> it works best on very bursty data.
<ali-as> If the first time I looked at your schematics I'd have seen a xilinx chip, I'd have joined this project straight away.
<whitequark> internally this is implemented by keeping several data FIFOs, an event FIFO that says which data FIFO has a value for which event, and a timestamp FIFO that stores deltas between samples.
<ali-as> I've never touched Altera before.
<whitequark> then, there is an encoder that collects all these FIFOs and converts them to an optimized byte stream.
<whitequark> for example the timestamps are 16 bit, so you need to insert a dummy event each 65536 cycles
<ali-as> It's higher level than I'm going to be able to follow on a first pass.
<whitequark> the encoder maintains a running tally with a 35 bit counter, so if absolutely nothing happens, it'll send just a few bytes per hour
<whitequark> it will also only report the actual events at any cycle that an event has happened
<whitequark> I also have special code that considers FIFO depth and width, and picks the block RAM primitive that is most suited for the geometry, in terms of not leaving unused silicon
<whitequark> ali-as: I don't use Altera.
<whitequark> I use Lattice.
<ali-as> Some of my early stuff on EJTAG was programing 4 keys on my keyboard to be TMS TDI 00 01 10 11, and the output was the state of TDO, and I spent hours just going through registers.
<ali-as> Cyclone is Lattice?
<whitequark> and in fact, the project would not be possible on any other FPGA family other than iCE40 when it was designed, and is still not possible on any other FPGAs other than Lattice's
<whitequark> I do not use Cyclone
<whitequark> I use Lattice iCE40, the iCE40HX8K in the latest revision.
<whitequark> the reason is, iCE40 has a completely open-source toolchain, and it is of extremely high quality.
<ali-as> Oh, I'm an idiot, I'm reading CY7 and that's Cypruss USB chip.
<whitequark> when you run an applet, the Glasgow software dynamically composes, synthesizes, places and routes a bitstream specifically optimized for whatever parameters you just requested.
<whitequark> for something like an UART, this takes... let's see
<whitequark> under 9 seconds of wall clock time.
<ali-as> I have nothing against Lattice either, but It's going to be a whole new toolchain to learn :/
<whitequark> from $ glasgow run uart, to having a bitstream loaded into the FPGA.
<whitequark> nothing is cached.
<whitequark> the tools are so fast, that caching would be a waste of space and a source of bugs.
<whitequark> can you see *any* xilinx tool *ever* producing a bitstream in 9 seconds?
<whitequark> with the amount of useless shit Vivado has, and the completely braindead way it is written, you are lucky if it will start doing anything useful in 9 seconds.
<ali-as> It's slow for sure, and I've not linked it to anything else.
<whitequark> also, you wouldn't really need to learn anything except Migen
<whitequark> Glasgow transparently handles things like pin assignment, USB request (both FPGA side and PC side), and even PLLs.
<whitequark> you tell it what frequency you want, and it automatically computes every parameter.
<whitequark> no "wizards", just a Python function.
<ali-as> I can't code in python.
<whitequark> you'll have to learn that to write Glasgow applets
<whitequark> Glasgow does *everything* in Python.
<whitequark> gateware in Python, host software in Python, UI in Python, etc
<whitequark> yes. no Verilog at any point
<whitequark> the reason is, remember my logic analyzer?
<ali-as> That's dissapointing. I'm happy with assembler (on a few CPUs) and some C. I want to learn either Verilog or VHDL.
<ali-as> Yes.
<whitequark> Glasgow sets things up so that your applet is automatically instrumented, with just a single command line option. then it adds the USB code to read the data from the logic analyzer. then it formats the binary stream to have the pin names you have assigned, regardless of the actual pinout. no more looking for "probe 13"
<whitequark> you can't do this in Verilog.
<whitequark> Migen, and (by extension as well as independently) Python, are critical components that make Glasgow what it is, and if I had to stick with C, I would have not bothered with the project.
<whitequark> (as a professional language designer I also think C is a disaster reprehensible in every imaginable way, but that isn't even very relevant here.)
<whitequark> (I hate Python too.)
<ali-as> I hated C++ when I tried to learn it, and when I looked at python, invisible formatting characters are part of the syntax.
<whitequark> doesn't matter.
<emily> spaces aren't invisible
<ali-as> I've heard of migen, but not used it.
<emily> ifyouinsisttheyarei'llstarttalkinglikethis
<ali-as> How do you tell a tab from a series of spaces?
<whitequark> arbitrary syntactic choices in a language almost never matter, and significant indentation is one of those
<emily> by never using tabs in python
<emily> it warns on them by default as of 3 i think? or maybe even rejects
<whitequark> emily: it rejects mixed tabs and spaces, yes
<whitequark> ali-as: there are far worse things lurking in Python's semantics, that's for sure.
<emily> tired: complaining about the off-side rule
<ali-as> I have a very hard time with anything high level.
<emily> wired: complaining about "global"/"nonlocal"
<whitequark> but the amount of expressive power it provides is enormous, and very important to Glasgow.
<whitequark> Glasgow is a high-level tool, fundamentally, because it abstracts almost everything from you.
<whitequark> it abstracts USB and makes it as if you had a FIFO between your PC and the FPGA directly instead.
<ali-as> That will be a problem for me, as the moment something doesn't work the way I need I won't be able to change it.
<whitequark> it abstracts pins and lets you define the pinout as a CLI parameter.
<whitequark> so, here's the thing.
<ali-as> So I might be better waiting for a working final version.
<whitequark> working final version?
<whitequark> there will be no version of software/gateware stack that is more final than what currently exists.
<gruetzkopf> I'm not sure that this project can have a final version
<ali-as> Sorry my understanding were that the versions were in flux and there was a plan for something like a kickstarter.
<whitequark> nope, I don't do kickstarters.
<whitequark> there is no need for more capital.
<whitequark> all we have to do is to replace one chip for revC1, test it, and then it's off to fab to be sold for anyone who wants a board.
<whitequark> if you don't care for configurable pull resistors (yes, on every pin. so you can do I2C with just four wires, no external passives!) then you can even order a revC0 board right now.
<ali-as> Hmm.
<whitequark> I'll tell you more.
<ali-as> If I wired that to JTAG....
<whitequark> eventually, there will be more and more powerful hardware.
<ali-as> Would that tell me if I'm on an input or a driven line?
<whitequark> this is the third hardware iteration, I changed the level shifters and the FPGA from the previous revision.
<whitequark> no applet code was modified.
<whitequark> even though I went from autosensing level shifters to explicit direction control signals.
<whitequark> that's the power of abstraction; I had a new board with half of the chips replaced, I spent maybe a day, and all of my dozen+ applets worked on it instantly.
<whitequark> just faster and more reliable :D
<whitequark> moreover.
<whitequark> there will be eventually revD (no LVDS bank, but 32 channels), and revE (a much faster FPGA with 5G SERDES).
<whitequark> any applet that runs on revA will run just as well on revE, which has a different FPGA family and completely reworked IO banks.
<ali-as> Only I've spent time with an oscilloscope an a series of high value resistors to ground and Vcc trying to identify TDO.
<whitequark> well, it'll be like five times faster, but other than that, no changes.
<whitequark> 14:39 < ali-as> Would that tell me if I'm on an input or a driven line?
<whitequark> there is already an applet called jtag-pinout
<whitequark> ali-as: this is a command I just typed: https://paste.debian.net/1071211/
<ali-as> Cool.
<whitequark> I never label the JTAG pins on my routers.
<whitequark> too much effort.
<whitequark> I plug Glasgow into a router more or less randomly, just caring for where the ground is.
<whitequark> then I ask it to tell me what the pinout actually is.
<whitequark> then I copy the CLI arguments it gave me, something like this...
<ali-as> (reads pastebin) O've blown away by this.
<ali-as> I'm.
<whitequark> this is another command I just ran.
<whitequark> copied the arguments from the jtag-pinout applet output.
<whitequark> it rebuilt a bitstream, instead of a bitstream optimized for pinout detection, it made a bitstream optimized for TAP probing.
<whitequark> ali-as: my *entire* MIPS code is under 1000 lines, and it deals in abstractions like write_ir and read_dr.
<whitequark> the JTAG layer provides a TAP abstraction, so if you have many TAPs on the chain? the MIPS EJTAG code doesn't care at all.
<whitequark> the other TAPs are automatically bypassed.
<whitequark> even better.
<ali-as> Do they have to be bypassed?
<ali-as> If you for example wanted to set a boundary scan pattern on another chip at the same time?
<whitequark> if you run the `jtag-probe scan` command, it will automatically segment DR to detect every IDCODE/BYPASS, and based on that information and what it knows about valid patterns in Capture-IR, it will automatically segment IR.
<whitequark> so if you have many devices in the TAP chain, most of the time (if it's possible at all) you don't even need to specify IR lengths.
<whitequark> of course, if you only have one device, it doesn't need any handholding at all.
<whitequark> 14:46 < ali-as> If you for example wanted to set a boundary scan pattern on another chip at the same time?
<whitequark> this is possible, but this code would have to be added explicitly.
* ali-as nods.
<whitequark> you would typically make an applet for your specific TAP chain, then delegate to MIPS EJTAG and whatever else.
<whitequark> the MIPS EJTAG code doesn't know what kind of underlying hardware it runs on, at all.
<whitequark> it just knows how to manipulate the EJTAG TAP.
<whitequark> you could definitely add some code that would manipulate another TAP in parallel, if you wanted.
<whitequark> you'd need to accept commands for the EJTAG TAP, and return results.
<whitequark> the EJTAG TAP code operates in terms of methods such as write_ir() and exchange_dr().
<whitequark> it doesn't care how exactly it's done. it doesn't explicitly specify state transitions either.
<whitequark> if you *do* need control over state transitions (e.g. say you want to go to SWD mode), that's possible.
<whitequark> you could operate in terms of functions like enter_shift_ir() and shift_tdio().
<whitequark> that takes care of the TAP state machine management for you.
<whitequark> (it selects shortest path)
<whitequark> this is how the SVF support is implemented. (yes, there's an SVF player.)
<whitequark> if you need even *more* control, you can operate in terms of shift_tms() and shift_tdio().
<whitequark> but you'd need to be careful to not confuse the rest of JTAG layer. you'd have to tell it what state it's in, or reset the entire thing.
<whitequark> the thing about abstractions is, well, MIPS EJTAG doesn't care about what happens on the TMS pin at all. it doesn't even care that there's a TMS pin.
<whitequark> so I want no traces of that in my MIPS EJTAG code.
<whitequark> but that doesn't mean I can't ever drop down to that level, if I have to.
<whitequark> and on the other hand? the abstraction gives me a lot of tools.
<whitequark> it lets me automatically bypass all the TAPs I don't want, since that's what you most often need.
<ali-as> I remember my code having to jump between JTAG chains, so I needed TMS.
<whitequark> it has a function that measures IR or DR length, in case you don't know it.
<whitequark> (MIPS EJTAG needs DR length measurement in fact, that's how you determine how many physical address bits you have...)
<ali-as> I had to hard code that.
<whitequark> no hardcoding.
<ali-as> And I kept making off by one errors counting.
<whitequark> three lines.
<whitequark> and one of them is a sanity check.
<whitequark> moreover.
<whitequark> abstraction lets me do something like this.
<whitequark> let's say I have an ONFI NAND flash and I want to program it in-circuit
<whitequark> but I have a chip that I know nothing about except its pinout, maybe I have a BSDL file and that's it.
<ali-as> max length 64. So it screws up if they ever make one longer?
<whitequark> no, it returns None, and the assert on the next line catches that.
<whitequark> (continuing) so I already have code to do JTAG, and already have code to do ONFI NAND.
<whitequark> the ONFI NAND code operates in terms of "set CE/CLE/ALE high/low" and "clock this data in/out".
<ali-as> This might be a dumb question, but if you are scanning a register that may contain junk, how can you be sure the length is right, because this kept me awake at night ;)
<whitequark> it doesn't really care how the physical bus is implemented.
<whitequark> so you make a small applet that receives commands from ONFI NAND code, and implements them in terms of JTAG transactions that twiddle BSCAN register bits.
<whitequark> it reuses JTAG code *and* ONFI NAND code. all improvements that are made to ONFI NAND code are available to you at no cost, forever.
<whitequark> if I add a massive NAND database tomorrow so that end users don't have to look up datasheets for the chips, it will be available to your JTAG flasher.
* ali-as nods.
<whitequark> Glasgow applets are like compound interest, the more I add, the higher the value, and it's kind of exponential.
<whitequark> imagine never writing an SPI driver or bitbanger again.
<whitequark> 14:59 < ali-as> This might be a dumb question, but if you are scanning a register that may contain junk, how can you be sure the length is
<whitequark> right, because this kept me awake at night ;)
<whitequark> there are two pieces of code that measure register length in Glasgow.
<whitequark> well, JTAG register length.
<whitequark> the simple piece of code is available for use for other applets, like MIPS EJTAG.
<whitequark> first, it shifts in max_length zeroes. this should have flushed the register, no matter how long it is, as long as it's under max_length.
<whitequark> second, it shifts ones until it shifts back an one.
<whitequark> third, it notes the data it shifted out in the very first step, and shifts it back, in case it was somehow important.
<whitequark> so when you exit through Capture-DR, your device doesn't emit magic smoke.
<whitequark> now, this works well if your device is well-behaved, and you already know you have a register there, and what's its size.
<whitequark> the more complex piece of code lives in the jtag-pinout applet.
<ali-as> max length for boundary scan can be thousands of bits, it's a really ugly thing to do to flush something ridiculous in linear time.
<ali-as> Just in case the next one is one bit longer than you ever thought.
<whitequark> it's actually very fast
<whitequark> I think I could make it even faster, so that even tens of thousands of DR bits would be scanned in ... about as long as it takes to do an USB transaction.
<whitequark> but it's not really necessary
<whitequark> well, hasn't been necessary yet.
<whitequark> if you come with some use case that needs to constantly scan multiple thousand bit DRs, I'll just make it faster.
<whitequark> hell, I could add some gateware, purely to accelerate scanning huge DRs.
<whitequark> you have ten square mm of silicon that's all just one giant DR? no problem, i've got you.
<ali-as> When I was doing ST20 I looked into merging my code with OpenOCD. I talked to the original author, who had taken a step back and a people had abstracted away the capture dr bit so that it had to terminate.
<ali-as> Which made it essentially impossible to do ST20 debug on it properly.
<ali-as> (JTAG is just a gateway for a sort of clocked version of the OSLink interface, which was the dark magic of ST20 debugging before JTAG came along)
<ali-as> So I'm really really excited by what Glasgow can do.
<ali-as> And I have a niggle that if someone I want isn't compatible it's going to be impossible for me to modify.
<ali-as> Umm, something.
<ali-as> Sorry, that may not have been very clear, for ST20 debugging you have to get into Shift-DR and then stay there forever (or until you want to stop debugging).
<ali-as> If you move to Exit-DR you have to restart a session and you may miss bits sent by the smart debug controller.
<whitequark> yes, I understood that.
<whitequark> you would have an applet that grabs the raw JTAG interface, i.e. if there are other TAPs, you would have to bypass them yourself.
<whitequark> then you would do:
<whitequark> await jtag_iface.enter_shift_dr()
<whitequark> output = await jtag_iface.shift_tdio(input, last=False)
<whitequark> the second line can be repeated forever.
<whitequark> it'll just stay in Shift-DR and exchange bits.
* ali-as nods. Cool.
<ali-as> I must not have touched ST20 in about 15 years.
<whitequark> so my current thoughts are, if I ever add "JTAG accelerator" to the applet, basically a small CPU with the JTAG master memory-mapped, you would always have a command that bypasses it.
<whitequark> you tell the FPGA "hold on, now I am going to send/receive raw TDIO bits"
<whitequark> that's not going anywhere.
<whitequark> what is ST20?
<whitequark> 15:10 < ali-as> And I have a niggle that if someone I want isn't compatible it's going to be impossible for me to modify.
<whitequark> I mean, that can never happene.
<whitequark> in the worst case, you write your own gateware to drive the JTAG interface however you want.
<ali-as> Well, that can happen, it can be written in python ;) I will probably never understand python.
<whitequark> there isn't really anything "built in" on the I/O bank side, you always implement some sort of interface yourself. you can reuse existing code.
<whitequark> you do get a lot of built-in stuff on the USB side.
<whitequark> you almost never have to care about USB's utterly braindead nature.
<whitequark> and utterly braindead OS USB stack implementations.
<whitequark> it even works on Windows.
<whitequark> very slowly.
<whitequark> 15:20 < ali-as> Well, that can happen, it can be written in python ;) I will probably never understand python.
<whitequark> so about that.
<whitequark> I am thinking about adding an RPC interface.
<whitequark> it would use https://google.github.io/flatbuffers/ for serialization
<whitequark> so instead of using Python, you could use C, to connect to the rest of the Glasgow stack via a socket.
<whitequark> then you would tell it "go to Shift-DR" and then "transfer these bits on TDIO".
<ali-as> Short hstory of the ST20, If you've heard of INMOS Transputer, well when they went bust/were eaten STMicro found themselves with a tiny 32-bit CPU, so when they made set top box chips something that took little silicon area was really useful and for about 10 years the most cost effective highly integrated STB chip had a ST20C2/4 CPU in it.
<ali-as> It's insane.
puck has quit [Read error: Connection reset by peer]
puck has joined #glasgow
<ali-as> I mean the ALU is like an RPN calculator. 3 deep register stack, push 5, push 4, add.
<ali-as> Half the instruction set is a descheduling point which means a task switch would currupt the stack and you have to reload your registers after every one.
<whitequark> huh.
<ali-as> At the peak of my understanding I wrote some debug trap routines. Nothing to tough. Circular buffers to feed data to the PC so I could on the fly rebuild debug messages that had been removed from the production firmware. I grew to like insane.
<whitequark> oh, that's a very common trick.
<whitequark> if C was a good systems language, C compilers would provide it natively.
<whitequark> Rust is *almost* there
<ali-as> Bare metal C is almost a thing. I was writing everything in assembler at that point.
<ali-as> Host stuff in tasm, ST20 stuff manually converting to hex.
<whitequark> I don't believe in writing assembly, personally.
<whitequark> Glasgow has a CPU core I designed for it, and its embedded instruction stream is composed using, you guessed it, Python.
<whitequark> there's also a MIPS not-assembler.
<ali-as> :)
puck has quit [Ping timeout: 246 seconds]
<whitequark> this will probably remind you of things.
<ali-as> I like assembler, cycle counting, pig tailing code.
<whitequark> I thought about shelling out to as, then thought again, and nah, generating instructions with Python it is.
<whitequark> cycle counting, hmm
<whitequark> so most of Glasgow gateware is designed around a single FSM that interprets command streams serialized through USB.
<ali-as> It didn't look like that, but that's familiar, saving the return address.
<whitequark> I think writing out FSM states by hand is silly and wasteful.
<ali-as> I used a mips assembler to get the hex and then pasted the hex into my source for the debug routines.
<whitequark> yeah, no, I'm far too lazy for that. I like easy to read code.
<whitequark> and easy to modify.
puck has joined #glasgow
<whitequark> I can even alter parts of it depending on which core I'm working with.
<ali-as> This was a few years after the ST20 stuff I did, things went high definition and STMicro moved away from the ST20, it wasn't really powerful enough.
<whitequark> anyway, I need to do some refactoring, but I'm going to make an FSM generator that takes a high-level description of your command set that you want between the applet gateware, and applet host software.
<whitequark> something like, "this command C sets FPGA reg X to the 18-bit value it receives over USB".
<whitequark> and then it generates all the logic required to make it happen.
<ali-as> I do Karnaugh maps manually too still ;P
<ali-as> I feel like a luddite, thanks for that, hahaha.
<whitequark> at one point I was not happy about synthesis results from my FPGA toolchain.
<whitequark> I considered doing K-maps for one millisecond.
<whitequark> then I found a paper from 1993 that describes a depth optimal LUT mapping algorithm, and implemented it for the synthesizer.
<whitequark> (runs in polynomial time, even!)
<whitequark> then I also wrote a LUT optimizer that can do things like...
<whitequark> suppose you have 4-LUT FPGA.
<ali-as> Do you need to do that for a LUT? It's basically a ROM.
<whitequark> no, I mean, FPGA LUTs.
puck has quit [Excess Flood]
<whitequark> the basic FPGA logic elements are lookup tables, used to implement arbitrary k-input functions.
<ali-as> Yes.
puck has joined #glasgow
<whitequark> right, so let's say you have an adder.
<whitequark> for each bit, you have an A input, B input, C (carry) input, and one output (assuming dedicated carry logic).
<whitequark> so that's a 3-input function in a 4-LUT.
<whitequark> now, adders are usually mapped to dedicated carry logic and LUTs using pattern matching in a synthesizer, as opposed to some generic synthesis method, because you want to take advantage of carry chains.
<whitequark> and carry chains usually have restrictions on routing.
<whitequark> now let's say you have an adder, A+B, and a mux after it, which selects A+B if S=0 and just A if S=1.
<whitequark> this is something you probably have in your ALU.
<whitequark> if you just run synthesis, the synthesizer will separately infer a chain of 3-input 4-LUTs for the adder, and then another chain of 3-input 4-LUTs for the mux.
<whitequark> but these 4-LUTs share one input and are chained, so it's possible to merge them into half as many LUTs, by moving the S input to the adder itself.
<whitequark> my LUT optimizer understands how to perform this transformation in the general case
<ali-as> I'm going to reread that again later till I understand it.
<whitequark> O <= S ? A+B : A;
<whitequark> think about how you'd implement this naively for 4-LUT architecture, and how it can be optimized.
<ali-as> (slightly embarresed) I can't understand that.
<ali-as> I'd interpret that as returning A+B if S is zero, A if S is 1, but it seems to be writing to 0 instead of a wire.
<ali-as> I am really bad at high level code.
<whitequark> that's O
<whitequark> not zero
<whitequark> bad choice of identifier, sorry.
<whitequark> R <= S ? A+B : A;
<whitequark> that's just Verilog.
<ali-as> Ok. R, A and B are busses, S is a single logic level?
<ali-as> If they are wires it's just SAB 000:0 001:1 010:1 011:1 100:0 101:0 110:1 111:1 in the LUT twice.
<whitequark> I don't understand.
<whitequark> where's carry?
<ali-as> I was a bit lost, you didn't say which were busses or how big they were ;)
<ali-as> You do mean + as in add and not OR.
<whitequark> right
<whitequark> A and B are say 16-bit busses.
<whitequark> it doesn't really matter how wide they are.
<whitequark> just think of a single unit of that adder/mux
<ali-as> CSAB R = 0000:0 0001:1 0010:1 0011:1 0100:0 0101:0 0110:1 0111:1 1000:1 1001:0 1010:0 1011:0 1100:0 1101:0 1110:1 1111:1 I think.
<ali-as> And we need a carry output for the next stage...
<whitequark> yeah, that's the single LUT solution.
<whitequark> but typical synthesis tools will infer a separate full adder LUT, and a separate mux LUT
<whitequark> (either that or using LUTs for generating carries, which is even worse)
<ali-as> I don't know how carry chains work in an FPGA. I'd have said CSAB C' = 0000:0 0001:0 0010:0 0011:1 0100:0 0101:0 0110:1 0111:0 1000:0 1001:1 1010:1 1011:1 1100:0 1101:0 1110:1 1111:1
<ali-as> I think I've made mistakes in my solution for R.
<ali-as> I think the last two bits should be 0.
<whitequark> that's fine, I would never compute a LUT by hand.
<whitequark> I'm far too lazy.
<whitequark> if it involves more than two bits I'd much rather have the computer do it, thank you very much
<whitequark> ali-as: oh by the way
<whitequark> I got distracted
<whitequark> ali-as: I have this command: https://paste.debian.net/1071235/
<whitequark> IR=11010 DR[96]
<whitequark> this is the register 0xB, FASTDATA.
<whitequark> has the correct size.
<whitequark> therefore BCM6348, which is what this router is, implements FASTDATA.
<whitequark> er, sorry, this is the register ALL.
<whitequark> FASTDATA is 0xE... and it's indeed missing.
<ali-as> ALL may not be the register I'm thinking of.
<ali-as> Yeah.
<ali-as> I think it was a special address in the EJTAG memory map.
<whitequark> ohhhhh, that's not FASTDATA then, that's FDC.
<whitequark> FDC has a set of dedicated FIFO registers in the MIPS accessible memory, FASTDATA does not
<whitequark> the FDC registers live in CDMM.
<ali-as> I'm not sure it was a FIFO. I'm not sure I have access to any of my code anymore.
<ali-as> It was also very badly documented at the time.
<ali-as> But it made a change from totally undocumented.
<ali-as> I think there was just a bit to enable it.
<ali-as> I do still have the STB, so I might wire it up and see.
<ali-as> bcm7038 based.
<gruetzkopf> i need to dig through my stack of DVB-S STBs and look for ST20, really
<whitequark> gruetzkopf: that's even more cursed than my stack of ADSL modems.
<gruetzkopf> (i kinda like writing transputer assembly, and doing it on a ISA bus ISDN card is getting ridiculous)
<_whitenotifier> [whitequark/Glasgow] whitequark pushed 2 commits to master [+0/-0/±2] https://git.io/fhxUF
<_whitenotifier> [whitequark/Glasgow] whitequark 30aa2d6 - cli: permute Python module names in logs for better readability.
<_whitenotifier> [whitequark/Glasgow] whitequark 47629ea - applet..jtag_pinout: adjust for jtag applet being renamed.
<gruetzkopf> (i mean, i could also implement the 16/32bit transputer serial interface, it's very simple)
<ali-as> ST20TP3, TP4, Sti55xx would be the SoC names.
<ali-as> It's a 32bit CPU, instructions are 8 bits long.
<ali-as> 4 bits opcode, 4 bits data, for primary ops.
<gruetzkopf> the OPERATE code is ridiculous :D
<gruetzkopf> you can technically chain 7 of them to shift in a 32bit instruction word :D
<ali-as> It's a lession in if you had never seen a CPU before, how might someone smart design one.
<ali-as> Was the ISDN card thing for work or school gruetzkopf?
<ali-as> Transputers were big at universities here. Wiring them into sheets and diamond lattice topologies.
<gruetzkopf> no, this is me using a commercial "active" isdn card from AVM as a devboard years later
<ali-as> Cool.
<ali-as> The ST20 TPx family have a single OSLink.
<ali-as> For TP2 this is the only debug you get.
<ali-as> Reset and Analyse!!!!
<ali-as> 20MBit OSLink was my first successful FPGA project.
<gruetzkopf> is OSlink still 2-start-8-data-1stop and 2-bit-ack like T2xx/T4xx/T8xx used?
<gruetzkopf> on LinkOut and LinkIn pins
<ali-as> Yeah, HH76543210L
<ali-as> And a single H is ack.
<gruetzkopf> yup, same thing
<gruetzkopf> okay, this one has a pinheader labeled ejtag
<ali-as> ST20 TP3 debug is done through JTAG, you set the right IR, then enter shift DR and while in shift DR what you have is essentially a clocked OSLink with TDI, TDO and TCK. The protocol is he same, HH76543210L and H to ack.
<ali-as> EJTAG is MIPS.
<gruetzkopf> (and around 50% unpopulated components)
<ali-as> ST20TP3 also has a debug controller though.
<whitequark> gruetzkopf: can you send me something with OSLink?
<whitequark> or wait
<whitequark> do you have a glasgow yet?
<gruetzkopf> i have a B
<whitequark> that should be sufficient
<whitequark> i need to make Glasgow network transparent, then
<whitequark> hrm
<gruetzkopf> i don't know if i have ST20 (iirc jn has some)
<gruetzkopf> i *do* have old-style transputers
<ali-as> Actual OSLink whitequark or ST20 with JTAG debug?
<whitequark> either, but I guess ST20 would torture Glasgow more
<ali-as> :D
<ali-as> ST20 with a real OSLink, you would be talking 1996-1998 sort of era.
<ali-as> It's primitive debug, halt and look at memory.
<ali-as> But you can also boot the CPU through it.
<ali-as> The JTAG protocol is utterly awesome and has direct memory access while the CPU is running.
<whitequark> huh
<ali-as> You don't feed any instructions, you can poke a trap handler into memory if one does not exist, put the breakpoint in one of the BP regs, arm the breakpoint in the config register and just wait for the CPU to hit it.
<whitequark> yeah, like all reasonable designs...
<ali-as> Makes EJTAG and the ARM methods look like they were written before we discovered iron tools.
<ali-as> Want to read a memory location? Start by feeding in the opcode for LDR....