Origen-SDK / o2

MIT License
4 stars 0 forks source link

Jtag prototype #128

Closed coreyeng closed 3 years ago

coreyeng commented 3 years ago

Hello,

I've added a JTAG implementation which follows the same structure as SWD. I also added a JTAG DP into our arm debug driver. The features themselves are limited. I'm not yet going for full driver support, but this PR takes us from "no-JTAG" to something we can build off of. It is definitely raw, and some things that may make @pderouen cringe, but its better than our current state I think.

This was tested on an internal device I'm working on here, so its actually been verified. I don't have specs, nor do I intend to do them quite yet, as I want to flush out this, swd, arm debug, and an internal driver I'm working, and see how things look at end. I think things are still a bit too fluid to want to make specs, examples, and documentation just yet, but they'll be coming (one of these "fluid things" being Capture Nodes as discussed in #125, and actually capturing in general, as well as overlays which are both unsupported right now)

I've also got a multi-pin internal driver working which is implemented as a service purely in Python (using the python plugin stuff), so there's some changes in there for that, but nothing that I think is controversial. The only thing I think I actually changed is allowing a default width in registers which will resolve to 32-bits with the defaults.

https://github.com/Origen-SDK/o2/blob/b4609b2a945adb57216f01654eb4e7abf6c1580f/rust/origen/src/core/model/registers/register.rs#L299-L304

One thing to note is I spun the Transaction struct that I use in driver to the Python side as well. Like the Rust-side counterpart, I want to use this as generic means to handle "incoming transactions". I plan to expand the pins to be accept this type as well, but that's not in this PR. This is used in my internal driver, but an example of generating one, which denotes a write transaction:

image

and allows you to do things like:

image

or

image

without needing to worry about what the input looks like. Its analogous to a lot of the clean addr or clean data stuff we had floating around the various O1 drivers, just in a more universal space.

pderouen commented 3 years ago

@coreyeng no cringing from me... maybe my standards are lower than you imagined :)

Is this implementation able to handle overlay/capture for 1 or more groups of bits?

coreyeng commented 3 years ago

Currently nothing handles overlays/captures! That's the next item up in my "protocols & subblocks" work.

pderouen commented 3 years ago

I more meant to ask if the data structures provide the capability to pass the info. I suppose that would come from the register whose ID is passed in the Transaction. I think the only thing that may be missing is a way to specify both read and write information in a single transaction.

coreyeng commented 3 years ago

That would be on two different pins though. I would rather think of it as two different transactions run in parallel. At least in O1, I'm not sure how this is handled, or if its even possible, as a register there doesn't hold both "read data" and "write data", nor does it here either (it resolves to "bits" which hold just a single state).

You can do it with enables if you wanted to read a few bits on TDO, then input some data on TDI (for handling the previous acknowledge, if that's what you're referring to here), but in terms of driving a full data word on TDO while comparing one on TDI, I think that should be thought of as two transactions run in parallel that the driver supports (obviously something like SWD wouldn't support this).

coreyeng commented 3 years ago

Here's how the current Bit struct looks:

https://github.com/Origen-SDK/o2/blob/master/rust/origen/src/core/model/registers/bit.rs#L19-L29

We can maybe re-purpose the device_state, but I don't think that was its intention.

pderouen commented 3 years ago

That would be on two different pins though. I would rather think of it as two different transactions run in parallel. At least in O1, I'm not sure how this is handled, or if its even possible, as a register there doesn't hold both "read data" and "write data", nor does it here either (it resolves to "bits" which hold just a single state).

In O1 you passed in a bit collection to the options hash to specify the read data when a write is happening.

It's actually all 1 transaction. JTAG registers are shift registers. As you shift in the LSB, the data currently held in the register's LSB is shifted out on TDO. I wouldn't want the driver to automatically care the out-going bits.

But, there does need to be a way specify it when we need to care TDO during a "write" or specify the data for TDI during a "read". Maybe an optional second Transaction passed in?

coreyeng commented 3 years ago

I think we need to keep "jtag transaction" vs. "transaction struct" nomenclature separate.

Its one transaction from the DR's perspective on Silicon, but two from the Transaction struct's in the code. Or, at least the current implementation of the struct. A transaction struct is meant to represent a single "do this operation on these pins with this data". I think making "operation" and "data" plural in that will get to be messy, partially because a register only holds one state at time, so you'd be "resolving to a transaction" twice. Which is what we'd be doing in O1 if you give jtag two bit collections, which I did find where that happens. I don't think the arm debug driver uses that, which is my main JTAG usage.

I think it make more sense to either give JTAG two transaction, one for read, one for write, and/or make another struct to represent multiple single transactions happening at the same time. Which, even though the DR is a single register, it amounts to two simultaneous transaction in the vectors.

pderouen commented 3 years ago

I think we need to keep "jtag transaction" vs. "transaction struct" nomenclature separate.

Yeah.

I think it make more sense to either give JTAG two transaction, one for read, one for write, and/or make another struct to represent multiple single transactions happening at the same time. Which, even though the DR is a single register, it amounts to two simultaneous transaction in the vectors.

Still agree that two Transaction structs with 1 being optional is the right choice for the jtag driver. The dp driver only ever needs 1 Transaction struct.

coreyeng commented 3 years ago

I opened #129 to track this. I think adding a way to do arbitrary parallel transactions would be better than making a one-off case for JTAG, but that's more involved than I wanted to take on in this PR.

pderouen commented 3 years ago

Ok, so you prefer to update the Transaction struct to allow parallel Transactions?

I'm fine with merging the existing code either way.

coreyeng commented 3 years ago

I'm thinking more of keeping the existing transaction the same but having another struct that is basically a vector of transactions and having some functions explicitly geared towards handling parallel transactions.

But, who knows. I may start down that path and that turns out to be worse. Will need to just start playing with it and see what it looks like.