[Libre-soc-dev] JTAG Boundary Scan in ASICPlatform
luke.leighton at gmail.com
Sun Nov 28 18:21:36 GMT 2021
Simulation() fails (clock domains are corrupted) if a Platform.build() fragment is attempted to be used by a Simulation().
the initial idea was (unlike for ls180) to have a new ASICPlatform auto-construct the entire coriolis2 build. of course, it is unreasonable not to attempt to simulate that.
with the failure of Simulation() to accept Platform.build() AST fragments, the initial plan is jeapordised and must revert to what was done in ls180: have a JTAG class construct the IO Boundary Scan.
this involves a near total rewrite of the ASICPlatform code, moving the Boundary Scan connectivity back into the JTAG class. however, the idea also is to use Platform Resource instances.
using Platform Resources involves putting them into a ResourceManager. ResourceManagers are "supposed" to only manage Platform Pins and Connectors. an FPGA Board has some pins that are connected e.g. to a UART ASIC, you have a "Resource" for that *specific* FPGA Board: J5 == UART0 TX, J6 == UART0 RX, ResourceManager allows you to "request" that pin resource once and only once.
if we are to have an ASICPlatform with a pinset (managed "Resources") then the JTAG Boundary Scan must have, know about, and understand, those exact same pins.
(otherwise, how can it connect pin-to-pin?)
where it gets more complex is that where previously the idea was to simply have an arbitrary pinset, where the Module knows absolutely nothing of any kind about JTAG, hand that to ASICPlatform and it auto-creates a full JTAG Boundary Scan, this is not going to work (Simulations fail).
therefore, it becomes the responsibility of the JTAG class not only to take care of wiring up cores (UART, I2C) to a JTAG core-side, it has to take care of wiring up to pads *as well*.
now there are two ResourceManagers needed:
* one for the jtag core resources
* one for the jtag pad resources.
bear in mind the names for each have to be identical. the top-level elaborate containing a JTAG instance no longer requests the *Platform* to provide the resource: it requests it from the *JTAG* module.
the JTAG Module then allocates both the core and pad resources, wires them up to the JTAG Boundary Scan Register, and finally hands the top-level module its Resource, as if nothing had happened behind the scenes.
as far as the top-level module is concerned, it got handed a Resource (UART TX/RX), thinking it got a pair of wires that are going to be connected directly to ASIC IOPads, but they're not.
the "hidden" (duplicate) PAD resource is then, only if Platform.build() is called, wired up to a THIRD ResourceManager: this one being inside the ASICPlatform.
the connectivity therefore goes like this:
* a periphersl core (UART, SPI) is instantiated as
* top level connects core to a Pin Resource,
thinking it is direct to IO Pads (as "normal")
* behind the scenes, a pair of Resources is created:
the "JTAG.core_mgr" one is what is handed to
* core_mgr wires are connected to the JTAG IO
Boundary Scan Register
* corresponding pad_mgr wires are ALSO connected
to the JTAG IO BS register.
* Platform.build() passes in an ASICPlatform to
the top level elaborate() which has a THIRD
identical suite of Resources
* the pad_mgr wires are hooked DIRECTLY to the
if Simulation() is required then this last step is not performed but the Simulation() may wire directly to the JTAG pad_mgr, which, due to that being one-to-one and onto the exact same ASICPlatform wires, is close enough to the actual ASIC wiring to not be of major concern.
the next step needed is unit tests and also a massive tidyup. today was a proof-of-concept day, to demonstrate that the above is going to work.
More information about the Libre-soc-dev