nelgau has quit [Read error: Connection reset by peer]
crzwdjk has quit [Ping timeout: 260 seconds]
crzwdjk has joined #amaranth-lang
nelgau has joined #amaranth-lang
nelgau_ has quit [Ping timeout: 255 seconds]
toshywoshy has quit [Ping timeout: 260 seconds]
mcc111[m] has joined #amaranth-lang
<mcc111[m]>
looking at https://github.com/ZiCog/xoroshiro/tree/master , realizing that although this code really seems to be designed as sample code there appears to be no license and no hint of a license anywhere in the code
<tpw_rules>
wow, parallax...
frgo has joined #amaranth-lang
frgo has quit [Ping timeout: 256 seconds]
<iposthuman[m]>
Doh! argh! I suffered a serious dyslexia 😬
<_whitenotifier-b>
[amaranth-lang/amaranth-lang.github.io] github-merge-queue[bot] 52159be - Deploying to main from @ amaranth-lang/amaranth@abd74ead55c3a0d43a0f8c1b30f34ca3ace53f3a 🚀
<omnitechnomancer>
I would definitely not call byte enables/strobes anything like bank select, as bank select brings to mind either the various SDRAM bank signals or something to do with addresses
frgo has joined #amaranth-lang
frgo has quit [Remote host closed the connection]
<iposthuman[m]>
Indeed. I agree.
frgo has joined #amaranth-lang
nelgau has quit [Read error: Connection reset by peer]
nelgau has joined #amaranth-lang
cr1901_ is now known as cr1901
frgo has quit [Remote host closed the connection]
<galibert[m]>
Wow, the unreliability of gcc/gnu ld for cross-compilation is impressive
<galibert[m]>
I'm at the point where I'm wondering if rewriting a systemd equivalent wouldn't be a better use of my time rather than trying to compile the real one
frgo has joined #amaranth-lang
Chips4MakersakaS has quit [Quit: Idle timeout reached: 172800s]
frgo has quit [Remote host closed the connection]
zyp[m] has quit [Quit: Idle timeout reached: 172800s]
peeps has joined #amaranth-lang
peeps[zen] has quit [Remote host closed the connection]
<zyp[m]>
can you elaborate a bit on how that'd look?
<zyp[m]>
I'm currently thinking about adding a platform proxy for my amaranth/litex/migen glue stuff so that amaranth code embedded in a litex build can request resources, and hacking up something similar to your platform.request2 sounds preferrable to hacking up something that mimics the existing platform.request
<whitequark[cis]>
zyp: not right now, but let's do this later
<whitequark[cis]>
PSA: Wanda has written an RFC for enumeration type safety, which is a breaking change of an unreleased feature that I would like to see us merge; please give feedback on the RFC https://github.com/amaranth-lang/rfcs/pull/31 and attempt to use the implementation in your projects: https://github.com/amaranth-lang/amaranth/pull/957 to understand how it serves (or does not serve) you
<whitequark[cis]>
cc galibert zyp adamgreig cr1901_ ktemkin
<ktemkin>
added to my todo list :)
<cr1901>
Ack. Will apply to trying-to-get-out-the-door project this weekend (on a branch)
<cr1901>
Pretty sure due to inertia I haven't even updated from enum to amaranth.lib.enum yet in that codebase
<galibert[m]>
Not convinced about rejecting comparison operators on non-IntEnum. It's useful when you have subgroups in your enum to avoid writing a lot of equalities
<galibert[m]>
lt/le/gt/ge are the ones I'm talking about
<whitequark[cis]>
thanks ktemkin! if I understand/recall correctly you have some relatively big codebases where introducing such changes can bring valuable feedback
<whitequark[cis]>
<galibert[m]> "Not convinced about rejecting..." <- I think you can make a method on your enum in that case, that uses comparison by .as_value() or something
jjsuperpower has joined #amaranth-lang
yuriks has quit [Ping timeout: 252 seconds]
<whitequark[cis]>
I think it does make sense that treating enum values as something that can fall in a range requires the same changes as treating them as plain numbers
yuriks has joined #amaranth-lang
<whitequark[cis]>
i.e. that the choice you have is between "linearly ordered" and "not ordered"
<whitequark[cis]>
<cr1901> "Ack. Will apply to trying-to-get..." <- thanks!
<galibert[m]>
We don’t have such a thing as an unordered, numbers assigned by the synth, enum
<cr1901>
enum.auto(), in principle
<whitequark[cis]>
I am not talking about the underlying representation
<whitequark[cis]>
I am talking about the semantics
<whitequark[cis]>
the reason enum.Enum is different from enum.IntEnum is that it communicates intent (of it not being treated "like an int") to anyone who is using it
<whitequark[cis]>
it does not matter whether it is, in fact, an int at the end of the day
<whitequark[cis]>
the difference between enum.IntEnum is that IntEnum has a linear order and downcasts to int implicitly, and enum.Enum has neither of those things
<whitequark[cis]>
you, I think, make a reasonable argument that these two properties are separate, and my response is that they're too similar to be worth distinguishing
<whitequark[cis]>
(especially given that the workaround is available and communicates intent, most certainly, better than having >= & < comparisons, especially because you can't do `e in range(E.A0, E.A15)` in Amaranth code, `__contains__` can only return an actual boolean, not a `Value`)
frgo has joined #amaranth-lang
<whitequark[cis]>
the effort of adding more type safety to Amaranth is all about semantics (as types always are); the underlying values are always going to be bit vectors, the toolchains are too immature to really ever delegate a decision such as encoding to them
<whitequark[cis]>
lib.data is about communicating intent, lib.wiring is about communicating intent (that is also machine-parseable in a powerful way), and lib.enum, after this RFC, would be about communicating intent by reusing semantics of enums in Python
frgo has quit [Ping timeout: 252 seconds]
<zyp[m]>
I don't have a strong opinion either way, but I don't think it'd be unreasonable to add comparison operators that enforce that both operands are the same type, i.e. in the same manner as FlagView.__bitop
<whitequark[cis]>
remember that amaranth.lib.enum is supposed to mirror Python's enum module exactly, or at least as exactly as feasible
<whitequark[cis]>
I do not disagree in principle but it doesn't seem readily feasible within that constraint
<whitequark[cis]>
(we are both overusing double negatives here)
<whitequark[cis]>
I feel that consistency with the built-in enum module is worth requiring downstream code to define a custom property that's in_some_range(self): return self == X or self == Y or ...
<galibert[m]>
ok yeah, that's a good reason
<whitequark[cis]>
yeah, that was the driving principle behind the design of amaranth.lib.enum the whole time; it seems I didn't make that clear
<galibert[m]>
I didn't know that property of enum.Enum in the first place
<whitequark[cis]>
well, the documentation stresses that point a fair amount, but maybe not enough
<whitequark[cis]>
> The amaranth.lib.enum module is a drop-in replacement for the standard enum module
<galibert[m]>
not everybody knows the dark corners of python like you do :-)
<whitequark[cis]>
right
<galibert[m]>
while you're in Enum, can we have a auto() that starts at 0?
<galibert[m]>
I know it's not strictly identical to enum.Enum, but there's a very, very good reason for that
<whitequark[cis]>
sure, can you write an RFC for that? it's a public facing change as well
<whitequark[cis]>
personally I'm in favor
<whitequark[cis]>
I think the only real question there will be naming, though of course others may have objections I don't anticipate
<cr1901>
IIRC, Python's auto() explicitly says to not rely on the starting value of auto()
<zyp[m]>
IIRC there's a hook to set it
<cr1901>
if that's correct, then changing the value isn't a public facing change?
<whitequark[cis]>
oh
<galibert[m]>
Hmm no, at this point I don't feel like writing RFCs or PRs
<whitequark[cis]>
then I guess you won't get your change
<galibert[m]>
Ok
<whitequark[cis]>
that said I just checked the docs for the built-in enum and you just want class FooEnum(enum.Enum, start=0):
<cr1901>
Looking at auto() docs, nothing about auto() default start is there. Maybe I hallucinated it
<zyp[m]>
TypeError: Foo.__init_subclass__() takes no keyword arguments
<cr1901>
nothing about auto() default start being impl-defined*
<whitequark[cis]>
also, you should not be surprised that if your first RFC is a redesign of a core part of the language, that it is not being given attention at a time when resources are scarce.
<whitequark[cis]>
surprised or disappointed
<galibert[m]>
And the second was something simple, and it got pocket-vetoed too
<whitequark[cis]>
I actually like the direction in #12
<galibert[m]>
maybe you didn't want to, but that's what happened, and I realized that was making me furious, and I didn't need furious in my life
<galibert[m]>
so now I'm feeling good, and I don't want to take the risk to change that
<galibert[m]>
because no matter what I like amaranth and I like what you do with it
<whitequark[cis]>
my point is that it is a mistake to be so invested in an RFC that a simple lack of attention (which was driven by the fact that at the time, in September, I was fighting several fires. my sister got almost murdered shortly after! anything that wasn't my direct responsibility at ChipFlow wasn't a priority) makes you furious
<whitequark[cis]>
there's an infinite amount of reasons why an RFC can lack attention, and this happens to everyone, including my coworkers. approaching them with a mindset that causes extreme emotional reaction is unproductive
<galibert[m]>
it's the three meetings where you skipped over it
<galibert[m]>
Is your sister ok though?
<whitequark[cis]>
yes, see the "my sister got almost murdered" part
<galibert[m]>
That would be the important part
<whitequark[cis]>
no, not at all. thanks for asking
<whitequark[cis]>
I remember why I skipped over it, and it was because I was essentially living in the middle of a panic attack 24 hours a day, and it was difficult enough to get through the things that were absolutely essential for the all-too-late release
<galibert[m]>
Is she in russia or in a less problematic place?
<whitequark[cis]>
your characterization of it as a "pocket veto" is wrong
<galibert[m]>
that's how it felt like
<cr1901>
galibert[m]: Two things are true: 1. I understand your frustration. 2. I don't think wq is obligated to air her dirty laundry to explain why she hasn't done something.
<whitequark[cis]>
you could have talked to me, for example.
<galibert[m]>
cr1901: I'm not asking her to
<galibert[m]>
I just explained why I steered away from directly contributing. Note that wq is very close to convicing me to try again though
<galibert[m]>
There's a level of fuckyness in one's life that excuses a lot
<cr1901>
I have complained about perceived slights in this room before. I can understand why it can come across as "being ungrateful for her hard work" too
<whitequark[cis]>
the fact that I don't like it isn't a veto either; I've had people convince me that things I have previously dismissed as obviously wrong are actually the right approach, however, even if I do think it's wrong I'd rather see it improved
<galibert[m]>
She's doing a beautiful work and I don't think I ever said the contrary (because I don't think it in the first place)
<cr1901>
I meant "I can understand why complaining about a perceived slight is something you don't want to do", for risk of being seen as complaining too much or "all you do is complain"
<galibert[m]>
Ah that. Ok, I agree with that
<whitequark[cis]>
I think as it is it's not a good fit for the standard library (mainly because we are adding three classes for something that's supposed to be straightforward; who's to say that someone won't need a fourth one, etc?), but that doesn't mean that some form of a strobe generator isn't a good fit for the standard library, or the documentation
<whitequark[cis]>
I was hoping to discuss that, and never got a chance to do so in the end
<galibert[m]>
Yeah, what I wanted was to discuss about it and see if we can reach something nice
<whitequark[cis]>
(if I wanted to veto it I would have simply closed it. if I feel like exercising power arbitrarily I do not need to hide it, I can simply do it)
<cr1901>
Btw: I haven't done the "amaranth CLI RFC" yet, because I do not have the concentration to churn one out right now. Writing hard.
<galibert[m]>
Good. Explicit vetos I'm actually 100% ok with. Some people don't dare though
<galibert[m]>
For some reason
<whitequark[cis]>
I mean, you've followed me for a while, right? I think you've seen me not being afraid of rather direct confrontation
<whitequark[cis]>
as evident by, you know, existence of Amaranth for example :p
<galibert[m]>
Dunno, being paid to work on it can change things, you're not really the only one in the decision tree anymore
<whitequark[cis]>
the whole point of the RFC process is that it is an acknowledgement of my fallibility and a request for others to fill in where I may not have the experience or the judgement
<whitequark[cis]>
galibert[m]: I am
<galibert[m]>
Especially begin paid to work on it by nice people
<whitequark[cis]>
ChipFlow has no operational authority over Amaranth
<whitequark[cis]>
this has been made extremely clear over and over to everyone involved, and acknowledged as such
<galibert[m]>
It's not so much as "Do/do not do this" but "you should be nicer to X or Y maybe"
<galibert[m]>
anyway
<whitequark[cis]>
I would treat such request in the same way as a request from any other member of the public
frgo has joined #amaranth-lang
frgo has quit [Read error: Connection reset by peer]
<whitequark[cis]>
I'm satisfied with basically every stakeholder currently involved being on the same page re: Amaranth being and remaining an independent open-source project
frgo has joined #amaranth-lang
<whitequark[cis]>
in practical terms, what it would take to revisit #32 properly (i.e. with an implementation that can be evaluated for breakage/UX/etc) is the new IR
<whitequark[cis]>
there is no ETA on it, but me & Wanda have been working on it
<galibert[m]>
Makes sense. There's also a series of open questions n #32 that could use thinking about
<whitequark[cis]>
yes. I think we'll have time to delve into that sometime in Q1 2024, the way things are going right now
<galibert[m]>
Plus some new ones, in particular around whether clock domains could be part of the interfaces
<whitequark[cis]>
I will finish the reference manual by that point, which will also give some input on ergonomics (which I feel are somewhat poor) of the current interface
<whitequark[cis]>
(I think you could have reopened the old PRs; as it is the numbers in the filename need to be changed, and the rendered content links are lost)
<whitequark[cis]>
(I don't really mind either way, but the filename is wrong right now)
<whitequark[cis]>
galibert[m]: yes
<whitequark[cis]>
this is something me and JF have been discussing recently
<whitequark[cis]>
I asked that it be left out of scope for the nearest release, in the interest of expedience
<whitequark[cis]>
but clock domains do need to be a part of the interface, in some way, shape, or form (I do not know which)
<galibert[m]>
I just resynced with upstream
<galibert[m]>
didn't think they were reopen-able
<whitequark[cis]>
they are!
<whitequark[cis]>
do you not have the "Reopen" button? you should have it if you closed it yourself
<whitequark[cis]>
I can also reopen them of course
<galibert[m]>
Just to be clear, I'm not looking for a merge, I'm very interested in the discussion
<whitequark[cis]>
yep, this is how the process works
<whitequark[cis]>
it has never been my intent to deprive you of that
<zyp[m]>
there's a reason it's called «Request For Comments»
<whitequark[cis]>
it would kind of negate the whole point of the RFC process if I was arbitrarily vetoing things before they get to be discussed, at which point I might as well not bother with the charade
<galibert[m]>
It felt like it, but I can accept it was just circumstances
<whitequark[cis]>
there isn't a committee set up by someone else that I'm capturing; I came up with the whole process because I believe it will result in a better language
<whitequark[cis]>
anyway. thank you for reconsidering
<whitequark[cis]>
let's discuss the strobe generator RFC on the next meeting, I'll make sure it's properly marked
<whitequark[cis]>
we'll have three items I think, metadata (final), enums, and strobe generator
<galibert[m]>
Next time something like that happens, just a "I know there's the strobe generator, but I'd rather discuss it later" would have been enough, fwiw
<whitequark[cis]>
metadata, enums, and yet-to-be-written RFC for taking care of VCD items for data.Struct (something you've brought up as well) are the things that are blocking the 0.4 release
<galibert[m]>
replace strobe generator by whatever
<whitequark[cis]>
yep, sure! sorry I wasn't clear on this earlier
<whitequark[cis]>
whitequark[cis]: because the release is so grossly overdue I think these three items should be prioritized, but once they're done (and in any spare time we have in meetings) we should discuss #26
<galibert[m]>
:-)
<whitequark[cis]>
also obviously nothing stops us from discussing it on the channel in non-meeting-time, such as right now
<whitequark[cis]>
(something that I think may not be entirely clear is that meetings are there basically to ensure we always have some measure of forward progress; they are not intended to entirely supplant any other discussion)
<zyp[m]>
(and to have the people available to vote at the same time)
<whitequark[cis]>
(yeah)
<whitequark[cis]>
I'm worried about the VCD for structs milestone issue, it's something I still have no real idea how to implement and it seems pretty important for usability
<galibert[m]>
Did you have the bandwidth to think about the slice-for-lack-of-a-better-name idea?
<whitequark[cis]>
so, I have some comments on the overall approach I'd like to see, which intersect with the idea but are not entirely specific to it
<whitequark[cis]>
I feel that the debug presentation of the value is a property of the shape, and ShapeCastable should offer a single Python property that is the entry point to determining presentation
<whitequark[cis]>
i.e. there should be a ShapeCastable.debug_repr (name TBD) which returns an object (TBD) that determines mapping from that bit pattern to VCD lines and such
<whitequark[cis]>
basically, I am (a) moving Signal(decoder=) from Signal to ShapeCastable, and I am proposing extending it to allow features such as "decoding to multiple lines in VCD"
<whitequark[cis]>
instead of being special cased, enums will simply come with a suitable value_repr that Signals of enum type would use
cr1901 has joined #amaranth-lang
<whitequark[cis]>
I do not have any real opinion on how the object returned by value_repr should look like
<galibert[m]>
I'm not sure, at this point, who knows the mapping between a field in a Struct and the underlying signal? The Struct or the View of the struct?
<zyp[m]>
whitequark[cis]: a dict of slices is what immediately comes to mind, or I guess rather tuples with slice indexes, since there's no object to slice yet
<galibert[m]>
zyp: you probably need some Cat() in there too, or an equivalent
<galibert[m]>
could be a list of slice indexes mind you
<zyp[m]>
by the way, how expressive is VCD? does signals/lines have anything more than bit width?
<whitequark[cis]>
we could go with something really simple such as a list of: self, another value, a dict of names to values, a function, a dict of names to functions
<whitequark[cis]>
zyp[m]: horribly inexpressive
<whitequark[cis]>
to display enums we are already using an extension (strings) by gtkwave, and the extension isn't very good
<whitequark[cis]>
whitequark[cis]: naturally, passing Python functions there would require Python to be in the loop when cxxsim is being used, which will slow things down
<whitequark[cis]>
(you can bypass that by requiring that the function be pure, which we probably should, in which case repeated invocations can be cached)
<galibert[m]>
that's why I was proposing the called-once-only slicing thing which gives the structure and can be used for both vcd and cxxrtl
<whitequark[cis]>
yes, I realize that
<galibert[m]>
and next to that the decoder to be used for vcd only
<whitequark[cis]>
and value_repr itself would be that called-once-only slicing thing (it is basically a factory object)
<whitequark[cis]>
however I do not think we should settle for thta
<whitequark[cis]>
s/thta/that/
<whitequark[cis]>
if we introduce functionality I think it should work across the board
<whitequark[cis]>
and cover more than just the direct immediate need that prompted its introduction
<whitequark[cis]>
what do you mean "for VCD only"? do you mean "for pysim only"?
<galibert[m]>
well, if you look at enum, you'd probably like to have the strings on the vcd side, and probably a C++ enum on the cxxrtl side
<galibert[m]>
well, for python only
<whitequark[cis]>
nope, CXXRTL does not translate RTL enums to C++ enums
<galibert[m]>
It could
<whitequark[cis]>
attributes on the RTL are treated purely as metadata
<whitequark[cis]>
I don't think it really could
<galibert[m]>
That way it could translate Struct to structs, etc
<whitequark[cis]>
you could have a 300-bit enum in RTL, which is completely fine right now, but it would break C++
<galibert[m]>
* The "same" way it could translate Struct to structs, etc
<zyp[m]>
I think slicing layouts into fields is an orthogonal problem to formatting enums and e.g. fixedpoint values
<whitequark[cis]>
since there is no 300-bit-wide type
<galibert[m]>
there's always constexpr, but honestly I'd go for best effort. enum when <= 64 bits, nothing special when not
<whitequark[cis]>
galibert[m]: this isn't possible at all since there are no structures at Yosys level, and thus CXXRTL has no way of knowing what a struct is, without introducing CXXRTL-specific attributes (which doesn't seem feasible)
<whitequark[cis]>
galibert[m]: what is the benefit of that though?
<galibert[m]>
using the names in the rest of the C++ code would be the reason
<whitequark[cis]>
if you make something an enum, it means you no longer have it in debug metadata
<whitequark[cis]>
(because debug metadata requires specifically value<N> and it is a part of our stable ABI)
<whitequark[cis]>
this means that now you have to write C++ code to interact with the enum
<galibert[m]>
the cxxrtl code doesn't actually have to use the enum, it's just nice to have it in the header
<galibert[m]>
so that you can use it in the c++
<zyp[m]>
IIRC you can choose which signals to include in the VCD, right?
<whitequark[cis]>
oh, well, I have no objection to that of course
<whitequark[cis]>
but it seems completely unrelated to this discussion
<galibert[m]>
same for the struct, you can generate an unpacking function that fills the fields
<whitequark[cis]>
you cannot do it for structs without first adding a new attribute in Yosys in general (I don't think a CXXRTL-specific attribute is the way to go)
<whitequark[cis]>
if you feel like making that work for Verilog too go ahead, but I don't
<galibert[m]>
but there you sure can split at the debug fields level in the first place
<whitequark[cis]>
zyp[m]: yeah
<iposthuman[m]>
i believe it is via the trace field: ```traces=soc.ports```
<zyp[m]>
whitequark[cis]: so I figure that could be extended to let you choose which subsignals to include as well, where some subsignals can have fast formatters like slicing, and other subsignals can have slow formatters that involves invoking python on a particular value
<zyp[m]>
the latter would have value on short simulations, and could be omitted on longer simulations where it'd be too costly
<whitequark[cis]>
galibert[m]: for CXXRTL, the bit relevant for this conversation is the bit where it reads metadata in form of attributes on RTL wires and then in the VCD writer it uses that metadata to generate human-readable values
<whitequark[cis]>
zyp[m]: that seems tricky to do
<whitequark[cis]>
we do not have the concept of a subsignal
<zyp[m]>
value_repr would return some sort of list of subsignals
<zyp[m]>
e.g. the keys if it's a dict
<whitequark[cis]>
how would you describe an enum using value_repr?
<zyp[m]>
name and value
<whitequark[cis]>
I don't understand
<zyp[m]>
maybe something return {'name': lambda value: value.name, 'value': ()}, where the lambda is a slow formatter and the empty tuple is a [:] slice
<whitequark[cis]>
btw, the way I see it, is that in presence of CXXRTL, what we need is a mini-language for formatting values whose functions admit (a) n-to-m mapping from signals to VCD lines and (b) are at least partially serializable for use in CXXRTL
<zyp[m]>
that's how I see it too
<whitequark[cis]>
zyp[m]: then CXXRTL would not have enum values, which is a serious issue
<whitequark[cis]>
(since a lambda is opaque to it)
<galibert[m]>
I think for that you'we need to decide what we'd like to be able to do at the cxxrtl level (possibly eventually pending rtlil evolutions) for at least the existing Shapes
<zyp[m]>
when passed a function, it'd need to invoke the function to format the value
<zyp[m]>
hence slow
<whitequark[cis]>
yes, but for an enum, you know the mapping beforehand
<galibert[m]>
s/'///
<zyp[m]>
kinda moot for enums which are cacheable
<whitequark[cis]>
it seems wasteful to do that considering enums are everywhere and need to be visible in CXXRTL
<zyp[m]>
but you wouldn't cache every value of a 16-bit fixedpoint
<zyp[m]>
or 16 is feasible, but you get the point
<galibert[m]>
What would "enum visible in cxxrtl" mean?
<galibert[m]>
Because the as_value() is already visible, obviously
<zyp[m]>
hmm, I guess you could provide a mapping
<whitequark[cis]>
galibert[m]: "A" and not "1" in the VCD file
<galibert[m]>
I have a feeling we're not talking about the same cxxrtl
<whitequark[cis]>
I'm confused
<whitequark[cis]>
right now, if you write an enum in your Amaranth design and simulate it, you will get "A/1" in your VCD file with pysim, and "1" with cxxsim
<whitequark[cis]>
this limits the usefulness of cxxsim a lot
<galibert[m]>
When I say cxxrtl, I'm thinking class generation I'm going to poke at using c++ and not going anywhere near vcd
<whitequark[cis]>
and the same happens for SV enums with bare cxxrtl
<galibert[m]>
You're talking pysim replacement?
<whitequark[cis]>
yes, but it's a general problem that affects cxxrtl in non Amaranth use cases too
<galibert[m]>
well, enum to enum string is a famous unsolved problem in C++ :-)
<galibert[m]>
with absolutely terrible solutions, of course
<zyp[m]>
<whitequark[cis]> "it seems wasteful to do that..." <- so for a type with a small set of named values, you could provide the names as a mapping instead of a function: `def value_repr(self): return {'name': {e.value: e.name for e in self}, 'value': ()}`
<whitequark[cis]>
zyp[m]: this means you can't have nested subsignals
<whitequark[cis]>
since the two dicts become ambiguous
<zyp[m]>
indeed, it'd have to be some more specific types
<whitequark[cis]>
(this is a problem for implementation of value_repr for nested structs)
<iposthuman[m]>
I made this diagram to try and see where i was going wrong, but it seems correct:
<iposthuman[m]>
I shouldn't need to specifiy vendor primitives via verilog?
<iposthuman[m]>
Of course I don't know how to do that...yet, from Amaranth.
<whitequark[cis]>
<zyp[m]> "hmm, I think we still have to..." <- I see them as parts of the same "serializable repr function" approach; do you not?
<zyp[m]>
I do, we just need to be able to stack arbitrary levels of extraction before we get to the formatting
<whitequark[cis]>
agreed
<whitequark[cis]>
so a hierarchy of classes like... ReprFields (splits into several VCD lines), ReprEnum (maps thru a dict, and generates an SV enum too), ReprFunction (arbitrary function), others?
<zyp[m]>
ReprSlice could be it's own, maybe
<whitequark[cis]>
I'm thinking ReprFields would allow any Value at all
<whitequark[cis]>
slice, cat, whatever
<whitequark[cis]>
or, hm
<whitequark[cis]>
maybe mapping from a value to another value should be separate, unsure
<whitequark[cis]>
and ReprInt just points to a value that will be displayed
<whitequark[cis]>
(which can be slice, cat, etc)
<whitequark[cis]>
it is also the default repr if no other is defined
<galibert[m]>
I feel like there are three things, tell me if I'm wrong. One is prettyfying vcd. The second is nicer interface for c++ calling into cxxrtl. The third is prettyfying cxxrtl-generated vcd
<zyp[m]>
the raw value could maybe be implicitly available always, eliminating the need for ReprFields in Enum and Fixedpoint
bob_twinkles[m] has joined #amaranth-lang
<bob_twinkles[m]>
Do you have the tools to verify that this is what's actually going out on the wires?
<bob_twinkles[m]>
or a simulation harness, as a perhaps slightly easier setup
<galibert[m]>
are you sure you handled the output enable correctly too?
<iposthuman[m]>
I do have the tools because the chips are BGAs and even my most tiny clips wouldn't work 😉
<iposthuman[m]>
s/because/but/
<iposthuman[m]>
I don't really know. I tried mimicking the specs Write cycle and even stretched the timing waaay out.
<iposthuman[m]>
It's funny because I really thought SRAM would be simple. I've got a 6809 chit chatting with retro SRAM chips so the principle should have worked 🤔
<iposthuman[m]>
What i'm concerned with is if I need to use a SB_IO primitive like the example verilog that is supplied.
<iposthuman[m]>
I have Machdyn'e Keks SBC and it has a PicoRV32 that interfaces with it.
<galibert[m]>
You're short-circuiting on the read a2 time
<whitequark[cis]>
<galibert[m]> "I feel like there are three..." <- I think there should be no user-visible difference between the two VCDs
<galibert[m]>
that's never a good idea :-)
<whitequark[cis]>
so I think there are two items: improving VCDs by whichever means are necessary, and exposing stuff in CXXRTL
<galibert[m]>
and no, you're not handling oe. I mean the d pins oe. They must be output during write, input during read
<galibert[m]>
right now you're either never driving the output or short-circuiting the pins when reading
<whitequark[cis]>
galibert: for exposing stuff in CXXRTL, because I am focused on making CXXRTL usable with Amaranth primarily (and some upcoming programmatic features) rather than manually writing C++, I suggest you implement the codegen changes you want yourself and submit them as a Yosys PR; I'm happy to rubberstamp the feature as long as it fits in (i.e. uses generic Yosys attributes and does not pessimize the existing case);
<whitequark[cis]>
opportunistically generating enums, with a mangled name, whenever metadata is present is 100% OK in my book
<whitequark[cis]>
the same for structs but you would also need to introduce an additional attribute, which is something that's not in my purview and which will probably need to be looked at by other Yosys maintainers
<galibert[m]>
Ok, makes sense
<iposthuman[m]>
Hmm. should OE be enabled during Reads and disabled during Writes?
<galibert[m]>
output enable, that means exactly the contrary :-)
<galibert[m]>
you want oe=1 when you want the fpga to drive the d pins
<iposthuman[m]>
So OE isn't the SRAM's output it is the FPGA's? I'm not sure i'm understanding. The SRAM chip has an OE input signal and the spec says to lower it during reads.
<iposthuman[m]>
From the perspective of the FPGA i'm telling the fpga pin to lower OE on the SRAM's input...yes?
<bob_twinkles[m]>
the FPGA pins have their own OEs, exposed as .oe on the object you get back from the Platform
<bob_twinkles[m]>
(sibling to .o)
<bob_twinkles[m]>
So sram_0.dm.oe[0]
<bob_twinkles[m]>
I think... it might share a single oe for the whole dm signal
<whitequark[cis]>
galibert: I tried to look into what it would take to have struct support in cxxrtl/etc
<iposthuman[m]>
Well now i'm totally confused. how does *dm* play into this? I'm looking into SRAMResource and i see the *oe* subsignal but nothing at all about *dm* having an *oe* part.
<galibert[m]>
bob_twinkles: there's in general one oe per pin
<bob_twinkles[m]>
(do reactions make it through the bridge? I 👍 that)
<iposthuman[m]>
yeah, i thought Amaranth handled the pin enable as part of the bitstream building. I don't need to control any *oe* on a pin when using verilog.
<galibert[m]>
iposthuman: (almost) all fpga pins are bidirectional. They have three ports, i, o, and oe. I for input, o for output, oe to decide whether it's an input or an output at a given time
<galibert[m]>
when using verilog you need to assign 'z' which is pretty much equivalent
<whitequark[cis]>
bob_twinkles: they do not
<whitequark[cis]>
(they are disabled on Matrix entirely)
<galibert[m]>
amaranth doesn't have z for a lok of very good reasons
<galibert[m]>
s/lok/lot/
<galibert[m]>
(even if it's annoying for certain types of bram)
<bob_twinkles[m]>
ah, I am beginning to recall some discussion about how to disable them in just the bridged channels on the 1b2 side and concluding that it's not possible without disabling them on the whole server
<iposthuman[m]>
I guess that is what i meant by not controlling it explicitly, but implicit by direction assignment
<bob_twinkles[m]>
will use my human words in the future
<galibert[m]>
yeah amaranth is explicit and 0/1 only
<iposthuman[m]>
hmmm. i 'm starting to think i got mixed into a different discussion 😬
<galibert[m]>
also the reality of the fpga is the i/o/oe trio, so it's amaranth that matches well and verilog the synth has ot hack around
<iposthuman[m]>
bob_twinkles (@_discord_277305331011420161:catircservices.org) are you talking about something other than my SRAM issue?
<galibert[m]>
s/ot/to/
<galibert[m]>
he's talking about sending reading emoji between discord and matrix
<iposthuman[m]>
ah
<galibert[m]>
s/reading/reaction/
<bob_twinkles[m]>
my last 2 messages were yeah, this channel is bridged to both Matrix and IRC (which is why galibert has a [BOT] marker for us). I was clarifying what parts of the chat protocol are actually bridged
<iposthuman[m]>
Ah!
olivier_galibert has joined #amaranth-lang
<olivier_galibert>
Well I'm here too, but heh 🙂
<iposthuman[m]>
So bob_twinkles (@_discord_277305331011420161:catircservices.org) your saying that my OE signal is mostly likely incorrect with my Read cycle?
<bob_twinkles[m]>
the oe on your data lines are incorrect during your read cycle yes
<galibert[m]>
Your d pin oe signals must be 1 when driving the d bus (e.g. on write) and 0 when not (e.g. on read). You never toggle them, so your code is wrong. Which state they actually are in I don't know
<whitequark[cis]>
note: there are two OE signals
<galibert[m]>
Catherine: in the Pin class?
<iposthuman[m]>
that's the impression i'm starting to get.
<whitequark[cis]>
one within the FPGA, one on the PCB
<galibert[m]>
ah yeah
<galibert[m]>
I'm talking about the within-the-fpga ones
<bob_twinkles[m]>
so somewhere there needs to be sram_o.oe.oe.eq(1) =P
<bob_twinkles[m]>
s/sram_o/`sram_0/, s//`/
<whitequark[cis]>
not if the oe pin is set as dir="o"
<whitequark[cis]>
which it is, probably
<galibert[m]>
what's needed is sram_0.d.oe.eq(0xffff) and sram_0.d.oe.eq(0x0000) in the appropriate places
<iposthuman[m]>
I'm using the SRAMResource which sets ```dir="o"```
<bob_twinkles[m]>
so "somewhere" turns out to be "in the guts of amaranth-boards" 😅
<galibert[m]>
If Catherine is paranoid, and she usually is, the d pins are probably input-by-default
<galibert[m]>
because you don't create a short with a pin you don't drive
<whitequark[cis]>
yeah
<iposthuman[m]>
ok. where is this Pin *oe* defined. If this is the case then ALL my signals that go to the SRAM chip have/need *oe* set/cleared. I've never needed to do this with verilog. it is part of the port direction.
<whitequark[cis]>
(Amaranth normalizes everything such that 1 means asserted/on/enabled
<whitequark[cis]>
* means asserted/on/enabled)
<iposthuman[m]>
Oh! I didn't realize that. Wow that is an eye opener. then i my syntax was basically doing nothing?
<galibert[m]>
sram_0.d.o.eq(0xdead) also needs a sram_0.d.oe.eq(0xffff) if you want to actually drive the bus from the fpga
<whitequark[cis]>
yes
<whitequark[cis]>
galibert[m]: `oe` is 1-bit wide always
<galibert[m]>
Catherine: you can't drive half the bus?
<whitequark[cis]>
nope
<galibert[m]>
ok, good to know
<galibert[m]>
then you need sram_0.d.oe.eq(1)
<galibert[m]>
and in WRITE_A4 you need sram_0.oe.eq(0) to stop driving the d bus
<galibert[m]>
* and in WRITE_A4 you need sram_0.d.oe.eq(0) to stop driving the d bus
<cr1901>
Remind me... the pins are the only place where tristates are represented in Amaranth (i.e. there's no specials outside of the compat layer)?
<whitequark[cis]>
yes
<galibert[m]>
Wow, a question on /r/FPGA is how many LUT4 are needed to implement 8-bit bit-reversal
<iposthuman[m]>
That is totally different to me. I've got a lot of research to do. when i've defined pins as *io* in verilog the yosys toolchain simply issued a warning but things still worked.
<cr1901>
So for an individually settable GPIO generic module, it's signature would look something like "Out(ArrayLayout(Out({"i": In(), "o": Out(), "oe": Out()})))" <-- this is NOT valid Amaranth syntax, I hope it gets the point across
<whitequark[cis]>
kinda
<iposthuman[m]>
i'm kind-of panicking because i can't find where in Amaranth docs that talk about manually controlling Pin direction on *io* type pins. Any suggestions as to where to look into Amaranth's code base?
<galibert[m]>
like, on the cyclone v if the drive of the fpga is not hard enough (and iirc you can set it up to be low) you could drive the pin (and the pad) harder externally, and that would be the value you see in .i
<whitequark[cis]>
this will be the usual case
<whitequark[cis]>
.i is connected to the actual pad at all times
<whitequark[cis]>
so if you overpower the output, you will read non-.o value
<galibert[m]>
Requiring amaranth to add a bypass on oe = 1 would be a waste of gates
<bob_twinkles[m]>
sounds like a good way to destroy an I/O buffer 🙂
<bob_twinkles[m]>
(overpowering an enabled output I mean)
<galibert[m]>
Catherine: the cv adds a bunch of stuff between the pad and the routing grid :-). But no bypass iirc
<cr1901>
On the old 6521/2 peripheral expanders, one port had the "external input can override the value read when the pin is in output mode" and another port had the "bypass to read what's actually stored in the output register"
<bob_twinkles[m]>
the FPGA could in theory have a big FET in front of the .i pin switching it to one of the rails but I suppose this is also considered a waste of area
<cr1901>
Idk why it was done like that, but...
<bob_twinkles[m]>
saves you bus transactions on switching the mode on a bidirectional bus I guess?
<bob_twinkles[m]>
(saves CPU <-> 6521 bus transactions if there's a bidirectional bus on the 6521's pins)
<cr1901>
I'm not sure I follow :(
<bob_twinkles[m]>
if you want to swap e.g. PORTA from output-> input because it's attached to a bidirectional bus you're about to read from, that requires a transaction on the CPU<->6522 bus to write to the control register
<bob_twinkles[m]>
which might not be possible to do on time, or at least wastes some cycles
<bob_twinkles[m]>
so the "external input can override value read on an output pin" behavior is useful in that case
<galibert[m]>
IIRC port a is pull up/drive down
<galibert[m]>
While port b is drive up/down + pull up
<galibert[m]>
In bed, not gonna recheck the schematics