-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pins #21
Pins #21
Conversation
Hi @coreyeng, Looks good. Enabling A few changes for consideration: I see you have a few ways of accessing individual pins, but I think we should firm up on one style that we will use across the board. I've just opened a ticket for that so we can discuss that one over there if required - #22 Where does the posturing term come from, do we need it? It seems to be just a data attribute (which gets combined with a state attribute to form the overall pin status), but the term is confusing to me as it makes it sound like it is more than that. Can we move the pins into Model. Having it with a dedicated pin collection at the top will limit us to only having pins at the top-level. In the model will mean that we can support multi-chip modules better in future by having layers of pins, though for now we can just concentrate on having them defined in the top-level. origen.dut.db.add_pin("", blah, blah) # First empty path arg means the top-level Also I think consistency is very important at this stage and the main thrust of this feedback is to keep everything heading in the same direction so that it feels like a cohesive framework rather than a set of individually designed components. If you think the way you have done things here have advantages vs. the way I am advocating then let's definitely have that discussion. Thanks! |
…ts ensuring pin API is available on subblocks as well as the DUT.
Thanks for the feedback @ginty! To answer the considerations:
I updated it to work as I described in my comment there. I updated the tests so you can see how it looks there. I think it sticks pretty close to the
This was my attempt at retaining the dut.pin('test').drive! Would be written as dut.pin('test').drive_high
tester.cycle() We could even return something that can call
I added some tests to make sure the pins are still available on the models. I can shift the actual proxy calls back to
Completely agree, and that's why I opened this a bit prematurely. Normally I'd of waited a bit to be more feature-rich and tested. If I'm understanding the |
Hi @coreyeng, Looks like we are agreed re. #22. I've opened #23 to discuss how to handle application of state to the DUT, I like the chained idea you mention here. Yes I mean that the call to Rust to add a pin should be through Then as long as a function has a handle on the DUT, then it can easily access both pins and regs, and specs, and timing and anything else it may need from it. I may as well also say that there is much more front end Python code here than I would really like or envisage, however I haven't been able to get an alternative system working yet, so I'm not going to block progress at this point. So the sub-blocks that I implemented at first does have a fair amount of shadowing on the Python front end - a pure Python object (a controller) is instantiated for every Model that exists in the backend. However, its kind of a lot of work setting up that mirroring since it means you need to maintain a Python version and Rust version of the same APIs. e.g. I think you have concentrated here on making a Python API available, however someone writing the JTAG driver in Rust in the future is going to need a very similar pin API on the backend and so that will need to be added in Rust too. I think one of the big features of this PYO3 library is that its system of marking up Structs with So when front end code calls I got stack overflow to help me with how to create such a function that returns a py class - https://stackoverflow.com/questions/59204849/how-to-implement-a-rust-function-that-returns-a-python-object-using-py03 Note that pyo3 supports definitions for all the magic methods that we might want to use to make such a class dict-like or to display nicely in the console - https://pyo3.rs/v0.8.3/class.html#class-customizations What I'm currently struggling with though is how to have such a class contain references to the DUT objects they represent - e.g. to the pin objects stored in PyDUT. I get the sense that this blog post holds the key, but its at a level of Rust-fu that is currently well above me: https://raphaelgomes.dev/blog/articles/2019-07-01-sharing-references-between-python-and-rust.html Its feeling to me right now that that is something we won't really be able to properly tackle until we get a good 6 months or so of Rust under our belts - I think here we are pushing up against expert-level stuff within our first month of using Rust. That will be a bit slower than just de-referencing an existing pointer, but its likely to still be quick compared to what we are used to and it still has the same external interface we want to end up with. Then, when our Rust skills are up to it (or maybe yours are already!), we can replace the internals with a more efficient lookup mechanism in future. So that's what I'm thinking, but I'm probably still a week or so from being able to show a proof of concept on the regs, but I would recommend that you think about experimenting along similar lines for the pin API in parallel. |
Hi @ginty, Okay, I think shifting back my container thing into db calls shouldn't be difficult. To answer the second point, the reason I have so much Python code now was to cache the pins on the Python side, which I thought is what you were doing with I also encountered all the lifecycle and borrowing issues with pyo3... the silver lining is it makes some design decisions for us. I tried at first storing references but that only works if we're okay with static lifetimes (which I'd assume we aren't!). |
Hi @coreyeng, I don't think we should really be aiming to cache much on the Python side, I think setting and getting attributes from the DUT should involve a round trip to Rust in both cases, at least until performance tells us we need otherwise. What's there for the regs right now is just me playing around, so sorry if I gave that impression. |
WRT to this @ginty comment: So we can simplify that straight away by making the pins live in the same DUT data structure as everything else (and which makes logical sense anyway). Wouldn't this also make it easier to export the DUT model in any external format (if needed)? |
Hi @ginty, Okay, sounds good! If I ax all the caching stuff, I think it'll naturally fall in line with what you want. And moving the backend access to |
@info-rchitect, yes, absolutely |
I am glad we are discussing this as I don't think the rest of us can contribute in a positive manner until the rust to python exchange pattern is created. Once this is done, wash-rinse-repeat will be much easier. |
Hi @ginty, Question as I'm looking to move pins into the |
@coreyeng, yes exactly like that |
@coreyeng, though note that the path arg is relative to the DUT, so it should be origen.dut.db.add_pin('sb', 'p') |
Hi @ginty, I think I've got enough here for some basic pin interactions. I've got a good start on pin groups as well, but I had some borrowing issues and had to shift everything back to the Most of the Python code is gone. The only remaining bits are added directly to I've got a lot of the dict-like structure for I've also got everything going through I got rid of I think that answered the main concerns we had before. I need to learn pytest some. Right now I've just got a bunch of stuff stacked up in a single test, but it shows the Python API I've got so far. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good @coreyeng, just a couple of non-blocking comments.
Thanks!
example/tests/pin_api_test.py
Outdated
|
||
assert len(origen.dut.pin_groups) == 1 | ||
assert 'test_grp' in origen.dut.pin_groups | ||
assert isinstance(origen.dut.pin_group('test_grp'), _origen.dut.pins.PinGroup) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kinda agree with @pderouen, is making the user differentiate between pins and pin_groups the right thing here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My main reasons were, we could return a consistent class instead of sometimes a pin and sometimes a pin collection. Also, I don't think we had an easy way to get pin groups or all available names which, from an auto-doc perspective is something we'd need. It was also a way to differentiate between a physical pin and a more abstract grouping of them.
Based on that, it seemed like just making them distinct was the way to go. We could probably meet in the middle and do something like:
dut.add_pin('p1')
dut.add_pin('p2')
dut.group_pins('p', 'p1', 'p2')
dut.pin('p1') #=> PinGroup of size 1
dut.pin('p') #=> PinGroup of size 2
dut.pins #=> ['p1', 'p2', 'p']
dut.physical_pins #=> ['p1', 'p2']
This way, I can return a consistent class, pins/pin_groups/aliasing will all work at the pins
level, and physical_pins
can return the actual hardware pins. From the Rust perspective, I can keep the same scheme of the pin groups just operating on the underlying pin objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be handled similar to regs. For regs most of the API will be implemented by a BitCollection
object which can contain one or more bits. That means from a user perspective there is no API difference between dealing with a single bit, a whole register or a partial register (and hopefully we can even extend that in O2 to be larger collections like multiple registers or even whole sections of memory).
Pins should probably be the same. Internally we should have a collection of all individual pin objects and a separate collection of pin groups - which don't contain the pins themselves but just the details of what pins are included in the given group and any other metadata associated with it.
Probably another collection would be a hashmap of aliases.
pin('blah')
should look up individual pins, alias and pin groups for a match and wrap the resolved pin(s) in a PinCollection
for returning to the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I think we're on the same page then. The only difference I have is I have a PinGroup
as a named PinCollection
.
… indexing classes from Py03. Have some basics working. Experimenting with cleaning up code duplication using macros. Added support for pin_collections as an anonymous pin group
…Copmleted group/collection indexing. Added Python-level tets. Added a bunch of error handling.
Hi, This took a bit longer than expected... mostly because I kept going on tangents and kept adding 'just one more thing' about six or seven times. Anyway, the initial concern should be addressed. See the test suite for example usage. I have three "pin-objects" now:
The physical pins can accessed using Some other notes:
Future Stuff:
|
…multiple pins at once, as in O1
… O1, instead of trying to be fancy and storing the IDs with which the group was created with. Added several tests to ensure adding groups of varying widths work.
This looks great @coreyeng, a lot of good stuff for me to learn from when doing regs. A couple of pin-related features which don't exist yet (I think) but which some of the O1 users got good utility from are:
Not saying that the addition of these should be coupled to this PR, but have a think about them to make sure that none of the decisions being laid down here are going to make such things un-necessarily difficult in future. |
@ginty Absolutely true, all of these O1 features would be a must have for all use-cases I have run into over the last 10 years. I do not think they should be coupled to this PR and think we can merge. |
Yes, I'll continue to add more pin features from O1. I still have some open items from #34 and I think I can get general metadata going, we can use that as a stop-gap then extract whatever ends up being useful there into their own thing. I expect pin roles, types, and functions to all be included at some point. I thought from our last meeting we didn't know exactly what package support would look like. I don't use it personally, but wouldn't mind putting something together if its a regularly used. |
@coreyeng I will start a new issue regarding package modeling and provide a lot of scenarios and how they can impact pin visibility and pin attributes. |
@info-rchitect, If what O1 has is sufficient, I can look into just moving that over here. I don't want you to have to add a bunch of details that's already present in the O1 docs. Its just not something I use. If there are changes we'd like to make a long the way, we can open an issue to discuss. |
@coreyeng for sure start with O1 docs but there are many new needs wrt pin modeling such as multi chip modules where we need to figure out how Origen will communicate to identical pins on different chips. Another simple example is introducing things like two pins at wafer sort being aliased to a single pin with a new name for a particular package. |
…id it backwards from O1. Support reset data/actions when adding pins.
…ath' are passing. Removed the few instances where 'path' was being verified. All tests pass.
Merge pull request #21 from Origen-SDK/pins
Hello,
This is a (pretty elementary) starting point for adding pins. So far, all I've got is setting a pin value (
posturing
) then setting anaction
(Drive, Verify, Capture, HighZ). See here for the Python-side API.I changed the API around from the Regs and SubBlocks do to fit more with what O1 had, where pins are added through
add_pin
on the DUT instead of brought in from a separate file. I don't object to the latter, and its on the to-do list, but I went with the old O1 API to start.I also moved the Proxy for pins behind a
dut.__proxies__
class, allowing the use ofpins
and other methods as in O1 and hiding the proxy further from the user. The proxy is still available directly fromdut.__proxies__['pins']
.Like I said, this is pretty basic at the moment. O2 is moving faster than I thought it would and since I diverged from Registers and SubBlocks I want to put this out as an alternative scheme. Some next steps for me in either a future PR, or just building on this one, more or less in order of priority:
There's some stuff floating around for this already. For example, I started a
PinCollection
struct but haven't gotten around to integrating, so its just dead code at the moment. But, it shouldn't be for long. I also think that there's enough here to get started with vectors and pattern generation though. And1)
shouldn't be too much a problem since I think the vector/pattern generation side will be on the Rust side.Thanks!