<josuah>
that might allow them to push commits in a free-running wheel style, without the overhead of community discussion and experiment things their way
<d1b2>
<Olivier Galibert> whitequark: happy that you like it
<d1b2>
<Olivier Galibert> I tried to write it in an almost-standardese way
<whitequark>
it's a good RFC. it's not written how I would it (obviously, since it wasn't me who wrote it) but it has very reasonable suggestions and is written well
<whitequark>
in terms of contents, there are a few things I would maybe do differently, but they're surface level
luffy[m]1 has joined #amaranth-lang
<d1b2>
<Olivier Galibert> that's what rfcs are for, tuning that kind of surface-level stuff ๐
<whitequark>
yes
<d1b2>
<Olivier Galibert> not clear what's different in practice between torii and amaranth
<d1b2>
<Olivier Galibert> Also, w.r.t domains, I suspect Reset needs a rfc of its own. Between sync and async and non-zero reset values, some clarity would be useful
<d1b2>
<Olivier Galibert> f.i. CV's FF has an async reset-to-zero, sync reset-to-given-value
<d1b2>
<Olivier Galibert> independant, of course
<whitequark>
Amaranth does not make a distinction between types of resets
<whitequark>
if a flop is reset, it is always reset to the init value
<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark 6ec3d48 - Deploying to main from @ amaranth-lang/rfcs@e5d83de15390aa61631b38faaa731841f4209a9d ๐
<FL4SHK>
making pretty good progress on my GCC port to my custom processor that I'll be implementing in Amaranth
<FL4SHK>
I got libgcc to compile
SpaceCoaster has joined #amaranth-lang
<FL4SHK>
...granted I did co-design the instruction set and the GCC port
<FL4SHK>
so some instructions are there for the sake of easier implementation of the GCC backend
<FL4SHK>
though I do think the instructions like that are good to have
<whitequark>
nice
<whitequark>
oh, would you be willing to take a look at the document I wrote?
<FL4SHK>
boy it'd be nice if HDLs like VHDL and SV had that kind of thing
<FL4SHK>
but I don't know if I'll be using those HDLs any more after I transfer to software dev at work
<whitequark>
so one thing that will be implementable with this is fixnums
<whitequark>
I think those should actually be in the stdlib
<whitequark>
fixnums and complex numbers
<FL4SHK>
what is fixnums, is that for fixed-point arithmetic?
<whitequark>
oh sorry, yes, fixpoint numbers
<whitequark>
s/fixpoint/fixed-point/
<whitequark>
crossed a few wires
<FL4SHK>
those are good to have in the language directly
<FL4SHK>
or, the library, as the case may be... but Amaranth is a lot like its own language
<whitequark>
Amaranth is a language
<FL4SHK>
sounds good
<whitequark>
(which is implemented as a library)
<FL4SHK>
I can see that
<FL4SHK>
how exactly does `Union` work
<whitequark>
same as in C
<FL4SHK>
hm, so it just re-uses the fields as other types
<FL4SHK>
C unions unfortunately involve UB...
<whitequark>
yeah
<FL4SHK>
I don't use them in C or C++ because of that
<whitequark>
but... that's the entire point of a union
<FL4SHK>
is it?
<FL4SHK>
hm
<FL4SHK>
I just have been using `memcpy` or `memset` instead
<FL4SHK>
which is fine if there are no virtual methods in C++
<whitequark>
in C and C++ this is preferable for UB reasons
<whitequark>
however in HDL you might have a situation where e.g. the same register is interpreted differently depending on a type field
<FL4SHK>
yeah, that's true
<whitequark>
if you have a functional block that sends a command to another, defining a union is a good way to let the compiler calculate all the sizes for you
<whitequark>
i.e. pick the size of the biggest command (plus command discriminator) for the command bus size
<whitequark>
I should actually describe that
<FL4SHK>
that sounds good
<whitequark>
there's an upcoming change that I think might make your processor a little bit more elegant
<d1b2>
<Olivier Galibert> you can have 16 bits that can be RGB 656, ARGB 1555, YUV 4.2.2 for instance. You can have amaranth unions being non-UB because the bit representation is explicit, and they end up very nice semantic converters
<whitequark>
> When creating a view, either only the target argument, or any of the name, reset, reset_less, attrs, or decoder arguments may be provided. If a target is provided, it is used as the underlying value. Otherwise, a new Signal is created, and the rest of the arguments are passed to its constructor.
<d1b2>
<Olivier Galibert> ok yeah, that's later in the doc
<d1b2>
<VA3TEC-Mikek-14362> Please forgive me, what does UB stand for? Union binary?
<d1b2>
<Olivier Galibert> Undefined Behaviour
<d1b2>
<VA3TEC-Mikek-14362> OK thanks.
<d1b2>
<Olivier Galibert> I didn't think value-castable meant writeable
<whitequark>
it can be writeable if it has .eq
<whitequark>
Amaranth places no restrictions here and data.View just forwards .eq to the wrapped value
<d1b2>
<Olivier Galibert> I'm trying to feel my way aroudn the named concepts there. If Layout is a Shape, can I write Signal(some_layout) and ignore the existence of View?
<d1b2>
<Olivier Galibert> or are some shapes signal-compatible and some not?
<whitequark>
this is a very good question. all shapes are signal-compatible, however right now Signal(some_layout) will always return a Signal, not a View
<whitequark>
sorry, I'm trying to find something I've misplaced
<d1b2>
<Olivier Galibert> so you need the view to get the access attributes?
<whitequark>
yes
<whitequark>
anyway, there was the idea that Signal(layout) should return a View instance
<whitequark>
so RFC 9 would allow you to pass a dict as a Signal reset value, but it will still return a Signal
<whitequark>
we would need a new RFC to let the Signal() constructor return a View
<d1b2>
<Olivier Galibert> I'm not certain whether the View really adds semantics or is just an implementation detail that's visible?
<whitequark>
I dunno what "adds semantics" means
<whitequark>
the view is what knows how to slice the bit container to give you fields
<whitequark>
the View is also what you subclass to add methods on your custom data structures
<whitequark>
you can't subclass Signal, for good reason
<d1b2>
<Olivier Galibert> yeah, but the fields are already in the shape which is taken by the Signal, so arguably Signal could be less dumb and handle slicing itself
<whitequark>
no
<whitequark>
that would mean we can never add another method on Signal without breaking backwards compat
<d1b2>
<Olivier Galibert> So the semantics added is the Signal-wrapping capability which allows you to be more flexible there
<whitequark>
I think so
<whitequark>
I mean, it's also important that amaranth.lib.data is completely independent from the core language
<d1b2>
<Olivier Galibert> Oh yeah, that is a good reason
<whitequark>
if you don't like it you can reimplement it yourself
<whitequark>
the core language gives you enough hooks to do so
<whitequark>
there's been many requests to have Signal(layout) return a view
<whitequark>
so it probably needs to be done, I'll draft an RFC later
<d1b2>
<Olivier Galibert> Docs-wise, "The View is value-castable and can be used anywhere a plain value can be used. For example, it can be assigned to in the usual way" doesn't work for me, since a Const is a value and value-castable and can't be assigned to
<d1b2>
<Olivier Galibert> If you do that you make the core language dependant on lib.data\
<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark 18de9e8 - Deploying to main from @ amaranth-lang/amaranth@4398575322bd07a03732f787b798daaa83107303 ๐
<d1b2>
<Olivier Galibert> hmmm, why is Union a View and not a Shape (add castable wherever you want)
<whitequark>
it's both
<whitequark>
Struct and Union subclasses themselves are shape-castable, and their instances are value-castable
<d1b2>
<Olivier Galibert> errr, why do you have both Struct and StructLayout then?
<d1b2>
<Olivier Galibert> (sorry, still trying to parse it all)
<d1b2>
<Olivier Galibert> ah duh you have UnionLayout too
<whitequark>
yeah
<d1b2>
<Olivier Galibert> ok, *Layout are the "core" shape structures, and Struct/Union/Array are facilitators/shortcuts
<whitequark>
there's no Array
<d1b2>
<Olivier Galibert> not Array then
<whitequark>
but yes
<d1b2>
<Olivier Galibert> Yeah, I wouldn't have written the doc that way (surprise! I'm not you!), but I get the gist now, and it's real nice
<d1b2>
<Olivier Galibert> so lib.interface is gonna build on that to handle directionality and connectivity?
<whitequark>
yes
<d1b2>
<Olivier Galibert> Then of course I want it yesterday ๐
<d1b2>
<Olivier Galibert> I really need to write my version of the documentation so that people who think like me have an easier time at it
<d1b2>
<Olivier Galibert> (I have no intention of forking the implementation, mind you)
<whitequark>
what is unclear?
<d1b2>
<Olivier Galibert> That a ValueCastable is a wrapper over the complete properties of a Signal (reset, bindness, storage) and not just a read-time transformation
<whitequark>
ValueCastable is not tied to Signal in any way
<whitequark>
right now there is no API documentation for ValueCastable at all, only the reference documentation (which doesn't really explain what it is from a Python perspective)
<whitequark>
we'll have that eventually
<whitequark>
and it should be written in a way that ensures people who think like you (and others too) understand it
<whitequark>
Sarayan: you can actually stuff two signals into a ValueCastable if you want
<whitequark>
data.View(layout, Cat(sig1, sig2)) is legal
<d1b2>
<Olivier Galibert> That the layouts are building blocks of shapes, and signal take shapes but only cares about them minimally. You need a View (which is a ValueCastable as per the previous definition) to actually manifest its properties
<d1b2>
<Olivier Galibert> In fact Signals, semantically, are only one simple version of ValueCastable
<whitequark>
no, that's not right
<whitequark>
Signals are Values
<d1b2>
<Olivier Galibert> (implementation is another issue, but as in my domains rfc I really, really don't want to care about implementation)
<whitequark>
hm
<whitequark>
we don't have the luxury of not caring about implementation
<whitequark>
these RFCs provide extensibility points for user code, which specifically extends the implementation (in a robust way)
<whitequark>
extending the implementation is the point
<whitequark>
that's what we're defining
<whitequark>
it's different for clock domains because clock domains aren't extensible by user code. they just exist
<d1b2>
<Olivier Galibert> Well, the way I tend to see those concepts is that, for me, an object is characterized by what I can do with it (I'm very formal mathematics there)
<whitequark>
you have a few ways to interact with them, take it or leave
<whitequark>
sure
<whitequark>
so the whole point of ValueCastable is that it's something that lets you do value-like things with it, but is not a Value
<whitequark>
(ValueCastable the class)
<d1b2>
<Olivier Galibert> And a core object in amaranth is Mumble, when Mumble has a shape, a reset value, a reset_less characteristic, has .eq and can bind to domains
<whitequark>
there is also value-castable (the language guide concept) which includes values, because there the difference doesn't matter
<whitequark>
it's horribly confusing to be honest
<josuah>
@Oliver Galibert: here is what I do to work around for now (untested until very soon):
<whitequark>
but I think we have to live with isinstance(Signal(), ValueCastable) returning False
<d1b2>
<Olivier Galibert> Oh sure, but that enters the 'implementation details' territory in my view of the world
<whitequark>
it's not an implementation detail because it's visible to everyone using Amaranth
<whitequark>
imagine asking a newcomer's question: "how do I tell if something is value-castable?"
<whitequark>
and isinstance(x, ValueCastable) is the wrong answer
<whitequark>
the right answer is Value.cast(x) and catch a TypeError
<whitequark>
which is very unintuitive
<whitequark>
s/asking/answering/
<d1b2>
<Olivier Galibert> My answer would tend to be "what are you doing that you would ever have to ask yourself this question?" ๐
<whitequark>
I wish it was an implementation detail, but I could not make it work that way
<whitequark>
compare to clock domain implementation, which will be visible to exactly the Amaranth maintainers and nobody else
<d1b2>
<Olivier Galibert> hmmm, still playing with semantics, what happens if you have s = Struct(a=5, b=5), m.d.domain1 += s.a.eq(42), m.d.domain2 += s.b.eq(666) and domain1 and 2 are not compatible?
<d1b2>
<Olivier Galibert> (I know the struct syntax is bullshit, but you get the gist)
<d1b2>
<Olivier Galibert> (damn, it would be a ncie syntax though)
<whitequark>
it's nominated for the next meeting but I think it's unworkable
<whitequark>
so I missed this: > 16:00 <d1b2> <Olivier Galibert> And a core object in amaranth is Mumble, when Mumble has a shape, a reset value, a reset_less characteristic, has .eq and can bind to domains
<whitequark>
and also this: > 16:05 <d1b2> <Olivier Galibert> hmmm, still playing with semantics, what happens if you have s = Struct(a=5, b=5), m.d.domain1 += s.a.eq(42), m.d.domain2 += s.b.eq(666) and domain1 and 2 are not compatible?
<d1b2>
<Olivier Galibert> annoying
<whitequark>
for the 1st one: is Mumble here referring to Signal specifically or just "the" Amaranth type?
<whitequark>
for the 2nd one: the same as if you assign half of a signal from one domain and another half from another
<whitequark>
which is, hm, exception right now I believe
<d1b2>
<Olivier Galibert> 1. The concept, which is shared by Signal and ValueCastable at least
<d1b2>
<Olivier Galibert> 2. Is it going to work out with Interfaces to require everything in it to be on (the same/compatible) domains?
<whitequark>
1. ValueCastable does not in general have reset_less or reset or .eq
<d1b2>
<Olivier Galibert> Well, substitute with View then for instance
<whitequark>
2. with Interfaces you can have individual ports be in different domains
<d1b2>
<Olivier Galibert> Ah, so an interface is not going to be over a struct but over a collection of structs
<d1b2>
<Olivier Galibert> Yeah, I have a difficulty with ValueCastable being either readonly or readwrite (or maybe rvalue and lvalue) depending on... not entirely sure what it depends on
<d1b2>
<Olivier Galibert> The semantics are a little moddy
<d1b2>
<Olivier Galibert> I understand where it comes from, ValueCastable is essentially defined by having as_value, which allows it to appear in a read context in place of a signal/value, and if you add .eq on a derivative you can make it inherit the properties of a writeable thing you've tucked in the object
<d1b2>
<Olivier Galibert> e.g. the Signal wrapped in the View
<d1b2>
<Olivier Galibert> because Python-wise you only really need the read aspect and have the .eq return a correct type
<d1b2>
<Olivier Galibert> ok, I have some shopping to do before it's too late, much thanks for the discussion, I understand many more things now
<FL4SHK>
whitequark: let me look at that
<FL4SHK>
so
<FL4SHK>
I can't seem to load the page
<whitequark>
you took too long ^^; it was shared from my laptop and now it's not I guess
<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark 21e9c77 - Deploying to main from @ amaranth-lang/amaranth@a5ffa38e643c73409ff392b23716f1ac434bb538 ๐
<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark 105bc34 - Deploying to main from @ amaranth-lang/amaranth@68e292c6810e6c7034d8b6122820feeb46a5b20c ๐
<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark 9d9e7da - Deploying to main from @ amaranth-lang/amaranth@7166455a6a23ce3a7b6808eada147567df927bb4 ๐
<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark 152ccd1 - Deploying to main from @ amaranth-lang/rfcs@7d5dbff82ff09b5dc6ba14f76489e23b3f34b9be ๐
<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark 1d442e7 - Deploying to main from @ amaranth-lang/amaranth@54d5c4c047f0d8dd010a599dc1fccbeafe026995 ๐