bob_twinkles has quit [Remote host closed the connection]
ldcd[m] has quit [Quit: Idle timeout reached: 172800s]
_whitenotifier-3 has joined #amaranth-lang
Guest18 has joined #amaranth-lang
Guest18 has quit [Client Quit]
Guest18 has joined #amaranth-lang
Guest18 has quit [Client Quit]
<cr1901>
jfng: I'm still working on making a CSR bus bridge fit. I don't think 8-bit CSR bus is gonna work; _A LOT_ of resources are spent down/up converting and I exceed 1280 LUTs by 100. 1/2
<tpw_rules>
is there a way to get the final verilog name of a particular Module object? i need to use it to create an assignment with quartus
<tpw_rules>
for some reason the (* blah *) syntax doesn't seem to work with this particular assignment either
<whitequark[cis]>
there is not, but you can get the final verilog name for a signal
<tpw_rules>
i think it has to be on a module
<whitequark[cis]>
you're out of luck
<whitequark[cis]>
which assignment?
<whitequark[cis]>
<cr1901> "OTOH, I found a low hanging..." <- this seems pretty normal
<tpw_rules>
i need to do `set_instance_assignment -name hps_partition on -entity <module>` in the .qsf where afaict <module> can be the name of any module type, preferably an empty one
<tpw_rules>
and i'd like that to automatically be done if you instantiate a particular Elaboratable in amaranth
<tpw_rules>
is there some way to register a callback with the platform or something?
<whitequark[cis]>
an empty one?
<whitequark[cis]>
what kind of callback?
<tpw_rules>
like in verilog it would just be `module dummy (); endmodule`
<tpw_rules>
a callback to add a toplevel module so i know the name and then call platform.add_settings
<tpw_rules>
yeah it just doesn't seem to listen to that
<tpw_rules>
i don't see any warning about unrecognized attributes
Degi_ has joined #amaranth-lang
<whitequark[cis]>
quartus is garbage, more at 11
<tpw_rules>
(this is to work around a bug in the first place)
<whitequark[cis]>
yeah idk
Degi has quit [Ping timeout: 276 seconds]
Degi_ is now known as Degi
<cr1901>
ERROR: Failed to expand region (0, 0) |_> (13, 17) of 1327 ICESTORM_LCs <-- yea, this is the best I can do w/ Wishbone2Csr on HX1K. While it's cool that it almost fits, I think atomicity is too much to ask for on a novelty design.
<cr1901>
whitequark[cis]: I don't have a coherent example/argument to give rn, but I wish I didn't have to create e.g. "an LED peripheral that takes 128 MB of address space" to remove a lot of address decoding bits. But... it's fine. At least I know how to do it now.
<whitequark[cis]>
I think that is fairly normal in resource constrained designs
<whitequark[cis]>
e.g. this is why you see 32-bit micros with like kilobytes of RAM dedicate half a gig to something
<tpw_rules>
it would be kind of annoying just for this but i could use add_file to add my module with a known name if there's no way to give a Module a known name
<tpw_rules>
(or a Fragment)
<whitequark[cis]>
and then add an instance, yes
<tpw_rules>
cr1901: i've written bits to sort of extend that stuff automatically
<whitequark[cis]>
alternatively, you could set your own attribute and look it up in tcl
<tpw_rules>
not in amaranth
<tpw_rules>
well they were but not with amaranth-soc
<cr1901>
Oh, I don't mind that part. I wanted the Decoder to be something like "okay, I have 4 register addresses. Allocate exactly 4 spaces in the memory map for this. Treat any other address not in that group of 4 as "don't cares/reserved/undefined/whatever".
<whitequark[cis]>
amaranth doesn't have don't cares
<whitequark[cis]>
it consciously chooses slightly bigger designs over having undefined behavior
<cr1901>
Well, the generated yosys Verilog certainly does :D (probably an optimization)
<tpw_rules>
do you know off the top of your head how to do that? if not i'll have to dig through the tcl docs. i assume add_settings will take arbitrary tcl commands
<tpw_rules>
yeah i just let it mirror
<whitequark[cis]>
cr1901: priority match doesn't count
<whitequark[cis]>
that's not in any way ambiguous
<cr1901>
If I extend the LED peripheral to take 128 MB (27 bits- just an example), a bunch of decoding bits that were previously zero before became "?" in the output yosys verilog. It works, just wish it didn't take me so long to figure out that my decoding was dense when I don't care (pun intended) about that
* cr1901
couldn't get sparse=True to meaningfully work last he tried
<whitequark[cis]>
hold on, what do you think sparse does?
<cr1901>
Incomplete address decoding/mirroring
<whitequark[cis]>
nope
<whitequark[cis]>
there is no such functionality in amaranth-soc
<whitequark[cis]>
sparse relates to translating e.g. a 8-bit bus to a 32-bit bus
<cr1901>
Then what does sparse do then?
<tpw_rules>
mmmm, quartus's tcl manual doesn't mention attributes at all. closest i can get i think is the ability to use name wildcards to find the module name
<tpw_rules>
which wouldn't be so bad
<cr1901>
Hmmmm
<whitequark[cis]>
if it is sparse, then one 8-bit word is mapped to one 32-bit word (and you need to do special code in the firmware to handle e.g. a write of a 32-bit register)
<whitequark[cis]>
if it is dense, then one 8-bit word is mapped to a byte of a 32-bit word (and you can just write normally)
<whitequark[cis]>
that is actually a space-saving measure
<cr1901>
Okay, this is relevant to my interests
<whitequark[cis]>
saves on combining logic
<whitequark[cis]>
basically, your accesses are atomic either way, but using sparse decoding lets you not have an FSM
<cr1901>
>special code in the firmware <-- how would you do a 32-bit atomic access then?
<whitequark[cis]>
you need to do it in order from first to last byte
<whitequark[cis]>
the atomicity is handled as long as the sequence is uninterrutped
<cr1901>
I ask b/c while I only have 8 bit registers in this design rn, I might add a 16-bit one to access the timer prescalEr
<cr1901>
When I used sparse earlier tonight, it optimized away my whole design. So that is probably a hint I was using it wrong
<tpw_rules>
related to the stuff earlier, is there a supported way to store elaboration state? i assume attaching random attributes to the platform is verboten
<tpw_rules>
and i want a flag that this magic module hasn't been added yet and needs to be if the user instantiates any HPS components
<whitequark[cis]>
HPS should in principle be an Amaranth Quartus platform component
<whitequark[cis]>
I think I don't actually want to support people doing this downstream using these weird hacks
<whitequark[cis]>
so, basically, nothing HPS-related is going to be actually supported (as in: support provided) until that's in
<tpw_rules>
okay, is that on the roadmap?
<whitequark[cis]>
there is no one actively working on this
<whitequark[cis]>
I don't fully understand HPS, certainly not enough to come up with a good solution
<whitequark[cis]>
but we can definitely land some interim solution, like this empty module thing
<tpw_rules>
i'm happy to prototype with my design i shared earlier, i'm revising it to be more Amaranth
<whitequark[cis]>
I suggest writing an issue and describing in detail what you actually want from the platform, what the proposed implementation will cover, and whatit would not cover (especially the latter)
<whitequark[cis]>
then we can figure out how to fit it in
<tpw_rules>
okay, i need to figure some more stuff out myself first, but i can keep an eye on that
<whitequark[cis]>
cool
<tpw_rules>
so is there any way to store design-generated state in the platform or so? or at least something attached to the "elaboration session"?
<whitequark[cis]>
not a supported one
<tpw_rules>
okay
<whitequark[cis]>
you can set an attribute on the platform but this is not guaranteed to not break
<whitequark[cis]>
in general we don't have a concept of an elaboration session or anything like that
<whitequark[cis]>
this is why this should live in the Quartus platform
<tpw_rules>
okay, i see. thanks
<whitequark[cis]>
well. Intel platform? except they are spinning it back off?..
<tpw_rules>
this stuff is also family specific
<tpw_rules>
so all the stuff you need on cyclonev is a cyclonev_hps_interface_<whatever>
<tpw_rules>
ooh, just thought of a horrible hack
<tpw_rules>
anyway. thanks for the discussion. i'll bring it to a meeting/issue when it's ready (for sure not tomorrow)
<whitequark[cis]>
cheers
<tpw_rules>
the order all the elaborate(self, platform) methods get called is undefined, right
<whitequark[cis]>
yeah
<cr1901>
>the atomicity is handled as long as the sequence is uninterrutped <-- do I have to add this logic myself? (and what constitutes uninterrupted? Next memory access period? next memory access to MMIO region?)
<cr1901>
Haven't deployed yet, but staring at the generated Verilog, I see what you're saying re: mappping low 8 bits to entire 32-bit databus and vice versa. But nothing else
<tpw_rules>
there's also no way to have a platform Resource have logic behind it, right
<whitequark[cis]>
next memory access to the same CSR bus translator
<whitequark[cis]>
tpw_rules: not yet, no
<whitequark[cis]>
it's not completely clear how to add that; that will almost certainly come after streams
<cr1901>
Ooooh, you have to use CSRs to opt into that
<tpw_rules>
okay. that seems like a very plausible way to handle the HPS stuff
<tpw_rules>
but i'm just spitballing internally for now
<galibert[m]>
What it this hps_partition thing for?
<tpw_rules>
at least on my quartus i get "Warning (330000): Timing-Driven Synthesis is skipped because it could not initialize the timing netlist" without it. qsys labels the module which has the HPS i/o like sdram and usb and stuff, i guess for synthesis
<tpw_rules>
s/synthesis/simulation/
<tpw_rules>
there's also other singleton stuff it would probably be smart to do, like making sure the boot signals and reset signals and unused bridges are appropriately strapped from the FPGA side
<cr1901>
I think in principle I can get sparse to work, but I can't actually find the goddamn I/O ports from reading the output Verilog, and somehow I think some reads are being eaten when I enabled sparse. Fun.
<galibert[m]>
Ah yeah, that warning I’d typically ignore
Wanda[cis] has joined #amaranth-lang
<Wanda[cis]>
alright, let's see if I'm coherent enough for one more RFC today
<Wanda[cis]>
hm. apparently not/
<Wanda[cis]>
* hm. apparently not.
<cr1901>
How do you print out the final addresses of CSRs? I haven't the slightest fucking idea where anything after the first 2 are
<cr1901>
(periph_bus is a csr.Decoder) print([f"0x{a[1][0]:0X} to 0x{a[1][1]:0X}" for a in periph_bus.bus.memory_map.windows()]) gives me addresses that appear relative to the start of I/O, but I can't tell whether they're 32-bit address or 8-bit addresses (sparse=True, FWIW)
frgo has quit [Ping timeout: 240 seconds]
<cr1901>
And well, I can't actually test all locations
<cr1901>
Yea, I'm gonna have to wait to see an example. I cannot get sparse=True to play nice with csr.Decoder. Either yosys completely optimizes my design away, or half the I/O isn't at the correct place.
<cr1901>
One of the most frustrating nights I've had w/ Amaranth so far, tbh. I need a break...
<davidpaul>
please tell me how should i implement ecall instruction of Risc V, and is it compulsory to implement csr's first in order to implement ecall?
<whitequark[cis]>
why are you asking RISC-V specific questions here?
frgo has quit [Remote host closed the connection]
frgo has joined #amaranth-lang
frgo has quit [Remote host closed the connection]
zyp[m] has quit [Quit: Idle timeout reached: 172800s]
frgo has joined #amaranth-lang
davidpaul has quit [Quit: Client closed]
davidpaul has joined #amaranth-lang
<davidpaul>
because i am working on my project which is based on risc v ISA that's why
<davidpaul>
and i have to implement risc v instructions through amaranth hdl
frgo has quit [Remote host closed the connection]
<jfng[m]>
@libera_davidpaul:catircservices.org the #riscv channel would probably be a better place for your questions
frgo has joined #amaranth-lang
<cr1901>
whitequark[cis]: I don't feel particularly well today, so I wish to skip the meeting. However, I took some time to look at the 2 new nominated issues: Shapelike/Valuelike looks fine to me, merge/unlikely that I'll change my mind. And "I would prefer `StdInterface` or `BareInterface` b/c I have a bit of a visceral reaction to the word "pure"".
<cr1901>
Do you object?
<cr1901>
jfng[m]: Will try after I rest to see if I can find what I'm doing wrong
<whitequark[cis]>
StdInterface is a no; I don't like BareInterface since "bare" doesn't mean anything
<whitequark[cis]>
"pure" means "free of anything but data storage, in particular side effects like elaboration"
<whitequark[cis]>
<davidpaul> "and i have to implement risc v..." <- you _have_ to?
<cr1901>
Oh like pure function. That's fine then.
<whitequark[cis]>
yeah
<whitequark[cis]>
what did you think it was?
<cr1901>
Pure as in "blessed"/"a state to achieve"
davidpaul has quit [Quit: Client closed]
<jn_>
my first association was "without side effects", but i still didn't understand it (i didn't think about it long and hard); perhaps the new name needs some documentation to explain itself
<cr1901>
In that case, merge for `PureInterface`, probably unlikely that I'll change my mind w/ changes. I'm sure the changes will be fine. Thanks for responding early, I'm gonna go rest :P
<whitequark[cis]>
there will be documentation
jjsuperpower has joined #amaranth-lang
<whitequark[cis]>
it is 1700 UTC, the time for the regularly scheduled Amaranth meeting
<whitequark[cis]>
who is attending today? Wanda has COVID, so she is not
<jfng[m]>
o/
<whitequark[cis]>
<cr1901> "Pure as in "blessed"/"a state to..." <- oh, that would be so cursed
Chips4MakersakaS has joined #amaranth-lang
<Chips4MakersakaS>
o/
<galibert[m]>
Maybe (in the train home, will dissapear at some point)
<galibert[m]>
After reading them, merge on both Wanda's RFCs
<galibert[m]>
In case I go poof
<whitequark[cis]>
anyone else? adamgreig? zyp?
<whitequark[cis]>
tpw_rules? crzwdjk?
adamgreig[m] has joined #amaranth-lang
<adamgreig[m]>
I'm more or less head deep in a wiring cabinet but might be around later on
<adamgreig[m]>
Swapping to UTC makes a little more awkward
<adamgreig[m]>
(as in, UK time swapping to UTC)
<galibert[m]>
yeah, same here. But otoh Catherine is allowed to have a life after work
<whitequark[cis]>
all right. we have four items on the agenda today; as before I am focusing on the 0.4 release
<whitequark[cis]>
while working on docs with mcc111 we have discovered that "interface object" and "`Interface` object" are extremely easily confused with each other, and literally the same in speech, so I decided the latter should probably be renamed
<whitequark[cis]>
any objections to the PureInterface name?
<whitequark[cis]>
(this RFC also frees up wiring.Interface name for something else if we want to use it later)
<Chips4MakersakaS>
No objections
<jfng[m]>
i like PureInterface; though in pathlib, Path inherits from PurePath, which is the other way around
<whitequark[cis]>
that's a different meaning of Pure so I think that's OK
<galibert[m]>
No objections here, it makes sense in the usual functional acceptance of the word
<whitequark[cis]>
this is a simple RFC so please respond with your proposed disposition: merge or close. @cr1901 voted merge
<whitequark[cis]>
right now, we have a discrepancy between the language guide and the actual language: the language guide calls Shape and things inheriting from ShapeCastable "shape-castables", but isinstance(Shape, ShapeCastable) is False
<whitequark[cis]>
there is the same problem with Value
<galibert[m]>
Is it more pythonic to have a class which redefines is* rather than a simple function like is_shape(object)?
<whitequark[cis]>
* right now, we have a discrepancy between the language guide and the actual language: the language guide calls Shape and things inheriting from ShapeCastable "shape-castables", but isinstance(unsigned(1), ShapeCastable) is False
<whitequark[cis]>
it would be very useful to have some X that you can call isinstance(obj, X), and moreover, when using type checkers, you really want to do things like def f(obj: X)
<galibert[m]>
Ah, type checkers, makes sense
<Chips4MakersakaS>
Like it, especially the use case for type checking.
<galibert[m]>
(poof in 2mn, still on merge for me)
<whitequark[cis]>
we are proposing we introduce ShapeLike and ValueLike as that X
<whitequark[cis]>
this is already something that Coreblocks are already doing in their type stubs, and I like the name
<whitequark[cis]>
questions?
<jfng[m]>
i currently use `try: Shape.cast(foo); except: ...`, which is not infallible (as the RFC notes)
<jfng[m]>
while the proposed `isinstance(obj, ShapeLike)` wouldn't be either, it is more readable
<whitequark[cis]>
no further questions, it seems
<whitequark[cis]>
please respond with your proposed disposition for RFC 35: merge or close. absentees: @cr1901 merge, @galibert merge
<whitequark[cis]>
we currently have an argument path= in several of the lib.wiring functions and methods. it means "a tuple of names leading up to this object, indicating the nesting of outer objects in a complex interface or similar"
<whitequark[cis]>
I have traditionally used path= for this in my work, but this isn't necessarily clear to others
<whitequark[cis]>
do any of you have better ideas?
<whitequark[cis]>
there will of course be a section on what is a "path"
<whitequark[cis]>
in the documentation I mean
<whitequark[cis]>
also, do any of you have strong objections?
<jfng[m]>
in favor of `path=`: it is often used in the context of a nested data structure, where each sub-structure has a "path" that is prefixed by the one of its parent
<_whitenotifier-3>
[amaranth-lang/amaranth-lang.github.io] whitequark d5a81bb - Deploying to main from @ amaranth-lang/rfcs@1727faec71b0ba0468b0b18e805c74f88c7fdb79 🚀
<_whitenotifier-3>
[amaranth-lang/amaranth-lang.github.io] whitequark f3238ce - Deploying to main from @ amaranth-lang/rfcs@09893fe7e629a8dab570132cb59a72f8b403bbd6 🚀
<whitequark[cis]>
we are making excellent progress towards 0.4! there is only one outstanding design issue, which is the details of how Component functions
<whitequark[cis]>
(it heavily intersects with the WIP documentation for lib.wiring that I am working on right now)
<galibert[m]>
I think we indeed need some discussion on that
<galibert[m]>
We can talk somewhere in the week when we have time
<whitequark[cis]>
I'm going to dump some of my thoughts on this right now, I think
<whitequark[cis]>
to recap: we have a lib.wiring.Component class, which is intended as an Elaboratable that is also an interface object, and which allows using Python variable annotations to build its signature
<whitequark[cis]>
the intent for Component is to be, in many ways, a marker class like Elaboratable: you should not in general see elaboratable interface objects around that are not components, since there is no advantage to doing so
<whitequark[cis]>
also, it is desirable to allow for generic components, which only build their signature in their constructor (and lack, or ignore, the annotations in the class)
<galibert[m]>
Ignore is bad
<galibert[m]>
Lack is ok
<whitequark[cis]>
(yes, but in some cases you might really want to do it, e.g. for debugging)
<whitequark[cis]>
(we do want to avoid ignoring on the default path)
<whitequark[cis]>
the major unresolved question here is: the Signature objects are mutable (in a restricted way, through += and freeze), which means that their lifetime matters, a lot
<whitequark[cis]>
this leads to two further questions:
<whitequark[cis]>
- what is the lifetime of the `Signature` object constructed from the class variable annotations?
<whitequark[cis]>
- what is the lifetime of the `Signature` object constructed in the `__init__` method?
<whitequark[cis]>
right now, the answers to these questions are "for however long the result of comp.signature is kept alive" and "at least until someone reassigns comp.signature to something else"
<whitequark[cis]>
I think both of these answers are wrong
<galibert[m]>
they sure are :-)
<whitequark[cis]>
the former, because it defeats our restricted mutability scheme, by, in effect, completely ignoring .freeze(). the latter, because comp.signature = x should not even be legal
<whitequark[cis]>
my view is that comp.signature = x should be forbidden; I propose replacing the current @property accessor with just return self._signature
<galibert[m]>
then it will be comp._signature?
<galibert[m]>
* then it will be comp._signature = x?
<whitequark[cis]>
yes, but that voids your warranty
<galibert[m]>
or it's a case of "you do that, you keep all 256 pieces"
<galibert[m]>
ok
<whitequark[cis]>
(you can break any abstraction boundary in Python, even that of function scope, but if you ever complain about this to anyone they tell you to keep all the pieces)
<whitequark[cis]>
I also propose making Component.__init__ accept a signature= optional keyword argument. in this case, exactly one of the two must be true: either signature= must be present, or the class must have variable annotations
mcc111[m] has joined #amaranth-lang
<mcc111[m]>
whitequark[cis]: oh, i like that.
<nelgau[m]>
I like that idea a lot
MuddassirAli[m] has quit [Quit: Idle timeout reached: 172800s]
<galibert[m]>
and no more arcane call to update and create_members?
<whitequark[cis]>
then we don't ever expose self._signature. we can even make it self.__signature or something (which expands to self._Component__signature
<whitequark[cis]>
galibert: I think you could already avoid that by calling the constructor after assigning `self.signature`, but yeah
<galibert[m]>
add a please_ignore_the_annotations_I_know_they_are_there_but_I_want_this_signature_instead = True for debugging?
<galibert[m]>
maybe a slightly shorter version
<mcc111[m]>
although if you do that, i think it will be an incentive to override __init__ and not call super, if you Know What You Are Doing and are making a signature within the object in a funny way. So you should explicitly document what the consequences are of overriding __init__ and not calling super.
<mcc111[m]>
(i'd say "well, you could just construct your signature in the child __init__, then pass the signature you made to the super __init__", but doesn't python have Weirdness around calling methods inside __init__?)
<galibert[m]>
then you error if signature != None and there are annotations
<mcc111[m]>
sigh, please assume all bolded inits were __init__s
<whitequark[cis]>
Python does not have weirdness around calling methods inside __init__; you may be thinking of TypeScript
<whitequark[cis]>
and yes, if you want to do something really weird you can just skip calling super()
<mcc111[m]>
I believe the problem I was thinking of is that although Python supports calling overloaded methods from __init__, you should not call methods defined by parent classes inside __init__ and before calling super init, as obviously the parent-class methods may rely on as-yet-uninitialized state.
<galibert[m]>
It adds an incentive to have the signature fully finished at constructor time
<whitequark[cis]>
yes, you should not call .signature before calling Component.__init__
ravenslofty[m] has quit [Quit: Idle timeout reached: 172800s]
<whitequark[cis]>
but this seems obvious
<whitequark[cis]>
you can't get a signature before you put it there
<mcc111[m]>
A broader point i was going to make: a thing that confuses me about signature objects is that … as Catherine describes, once the signature object is in place, it can be modified (using += only?) until .freeze is called. But as an end-user developer, it is not really possible to build a mental model around that because you don't know when .freeze is called. Can any clear user-facing statements about when .freeze will be
<mcc111[m]>
called be made? At least something like .freeze will not be called until…"
<mcc111[m]>
* A broader point i was going to make: a thing that confuses me about signature objects is that … as Catherine describes, once the signature object is in place, it can be modified (using += only?) until .freeze is called. But as an end-user developer, it is not really possible to build a mental model around that because you don't know when .freeze is called. Can any clear user-facing statements about when .freeze will be
<mcc111[m]>
called be made? At least something like ".freeze will not be called until…"
<whitequark[cis]>
".freeze() will be called whenever a decision based on the content of the signature is made elsewhere in the code"
<mcc111[m]>
Both of my comments here are poking at edge cases, but Catherine seems to think this second edge case (of appending to a signature after it is created) is fairly important
<mcc111[m]>
whitequark[cis]: ok, that's adequate
<galibert[m]>
I think a better model could be "the signature is set in Component.\_\_init\_\_ and the interface members are created"
<galibert[m]>
where set means frozen in fact
<whitequark[cis]>
well, you can't mutate a signature in other ways (although you could potentially mutate other objects attached to the signature)
<galibert[m]>
So there's no explicit "freeze" except for very advanced rare cases, it's just you create the signature in any way you want and you send it up, done
<whitequark[cis]>
galibert: I agree, `SignatureMembers.create` should freeze the signature
<whitequark[cis]>
(not specific to Component)
<galibert[m]>
And in such a view it would be sane to allow more editing of a signature object that has not been sent up (I'm thinking deleting fields for instance)
<whitequark[cis]>
yes
<whitequark[cis]>
er, sorry, deleting fields? no
<whitequark[cis]>
that's very deliberately forbidden
<whitequark[cis]>
the reason is that you might want to depend on the existence of a field if you're being passed an incomplete signature anyway
<whitequark[cis]>
i.e. I want some invariants to be still available even on un-frozen signatures, like that all of the fields that are there will stay there with the same shapes
<whitequark[cis]>
anyway, there is one last unresolved question
<whitequark[cis]>
for a class with variable annotations, should there be one Signature object per class, or should there be one per instance?
<whitequark[cis]>
in favor of one per class: this lets you call MyComponent.signature
<whitequark[cis]>
in favor of one per instance: (a) it's fiendishly difficult to make a read-only class property (you need metaclass stuff I'd rather not use), and (b) calling signature.freeze() may not necessarily freeze some ancillary objects, like the memory map (indeed, if you want Decoder to be a component, you very much do not want signature.freeze() to freeze the memory map, since then you wouldn't be able to add stuff to it; and
<whitequark[cis]>
there isn't a good way to freeze the memory map in this case anyway, since frozen is a flag on the signature members object, not the signature object itself)
<whitequark[cis]>
also (c) this matches with what the super().__init__(signature=) case is doing, which is nice and has fewer surprises
<whitequark[cis]>
I think (b) is the killer here for the "one per class" option
<crzwdjk>
I think once per instance makes sense for consistency, and also for the other reasons
<mcc111[m]>
I could easily imagine making "singleton" interface objects which have no corresponding class and are made by a factory or something, and which have bespoke signatures totally unique to that single object.
<mcc111[m]>
(unless by "per class" you mean "per component subclass", but i could also imagine for whatever reason designing my singletons as component subclasses.)
<mcc111[m]>
so i guess uhh are you saying "one signature object per class?" is a rule, or a default?
<whitequark[cis]>
for bespoke signatures we have anonymous signatures, wiring.Signature({...})
<whitequark[cis]>
mcc111[m]: I meant only in the context of components with variable annotations
<mcc111[m]>
ok thanks for clarifying
<whitequark[cis]>
which is a pretty specific sub-case
<zyp[m]>
sorry, I missed the meeting because I were out skating with the kid
<zyp[m]>
I read through the backlog and I'm in favor of everything that was decided and also very much in favor of `super().__init__(signature=…)`
<zyp[m]>
<whitequark[cis]> "I also propose making Component..." <- are we removing the ability to do neither and instead override the `signature` property?
<whitequark[cis]>
yes
<adamgreig[m]>
+1 from me too
<zyp[m]>
okay, that is fair, I have no arguments for keeping it
<whitequark[cis]>
thank you zyp adamgreig! looks like we are on track to release Amaranth 0.4.0rc1 next week :D :D
<zyp[m]>
nice
<galibert[m]>
Very cool
<adamgreig[m]>
🎉
<adamgreig[m]>
I meant to ask if I should update the crc generator in lib.crc with the lib.wiring stuff
<adamgreig[m]>
And if so whether that's an RFC or just a pr to amaranth
<whitequark[cis]>
we also wrote ~8kb of docs for lib.wiring yesterday
<whitequark[cis]>
the whole document is at 13kb right now
<zyp[m]>
adamgreig[m]: adding a signature for the existing interface wouldn't be a breaking change in any way
<adamgreig[m]>
Doesn't need to be a breaking change to require an RFC though
<adamgreig[m]>
Adding it in the first place wasn't either :p but yea I assume it wouldn't need one
<whitequark[cis]>
so right now none of our standard elaboratables use lib.wiring
<whitequark[cis]>
I'm not sure whether it's better to do it piecemeal or all at once
<whitequark[cis]>
I don't have a strong opinion on it
<adamgreig[m]>
I guess the question is whether it's done for 0.4 or not
<crzwdjk>
Given it's backwards compatible I think piecemeal is fine
<mcc111[m]>
..i have just discovered a deeply weird behavior in Element where if you use the party popper reaction it draws a little animated burst of confetti
<adamgreig[m]>
Yep! I think there's animated snow too
<mcc111[m]>
however, if the party popper reaction is drawn when the tab is backgrounded, it waits until the tab foregrounds, by which point the conversation may have moved on leaving the popper offscreen
<mcc111[m]>
so i just now entered this channel and after a second or so saw unexplained confetti floating down from the top of the screen to the bottom
<mcc111[m]>
This is not a complaint I'm just … hm.
<whitequark[cis]>
lol
<tpw_rules>
zyp[m]] <whitequark[cis]> "I also propose making Component..." <- are we removing the ability to do neither and instead override the `signature` property? <-- you said yes, what does this mean for overriding the property in general? will it be illegal somehow?
<tpw_rules>
like i understand that the wiring.Component machinery might not use such an overridden property
<whitequark[cis]>
tpw_rules: `self.signature = x` will just fail, yes
<tpw_rules>
maybe i misunderstand override. what happens if you do @property def signature(self): ... on your wiring.Component subclass?
<whitequark[cis]>
sorry, above, by "overriding" we meant "reassigning"
<tpw_rules>
okay that makes sense
<tpw_rules>
does this mean overriding the property in a subclass will continue to work and be compatible with the wiring.Component machinery?
<whitequark[cis]>
the lib.wiring machinery will use the definition of signature whoever does it
<whitequark[cis]>
since that's how an interface object is defined: an object with a signature property
<whitequark[cis]>
it is not completely impossible to forbid overriding it but it's pointless
<tpw_rules>
okay
<tpw_rules>
then the "must have class-level annotations, or must pass signature to __init__" applies to wiring.Component.signature, and would stop applying if you over-rode it somehow
<whitequark[cis]>
it's enforced in the constructor
<whitequark[cis]>
it stops applying if you don't call the constructor, in which case you also need to override the property
<tpw_rules>
okay, that sounds good
<whitequark[cis]>
but ... you could also simply call the constructor with the signature you want. does that not cover your case? do you want to override it for some reason?
<whitequark[cis]>
that's something I'd like to understand and address
Effilry is now known as FireFly
<tpw_rules>
it's not relevant anymore with the comment about pulling out the MemoryMap from csr.Signature. i just wanted to make sure i had a transition plan until that happened
<whitequark[cis]>
ah
<tpw_rules>
the use case would be "i want my wiring.Component to have class-level annotations to describe the connections, but for Reasons i have to insert a MemoryMap into the Signature, so it has to be attached later and can't be in the annotations"
<tpw_rules>
and my transition solution is to just override `signature` and add the csr.Signature later
<tpw_rules>
(assuming i remove the current crimes)
<tpw_rules>
thanks again for the work you do on this, looking forward to the official 0.4
<_whitenotifier-3>
[amaranth-lang/amaranth-lang.github.io] github-merge-queue[bot] 0ea3e92 - Deploying to main from @ amaranth-lang/amaranth@0cdcab0fbbdd86390fd32105f695a164e0826ab8 🚀
<cr1901>
jfng[m]: I've tried to create a SoC that tries to use a sparse Wishbone2CSR decoder. While the gateware compiles, the memory map returned by all_resources is incorrect, and in addition, it seems like half the peripherals are nonexistent. I have no idea why: https://github.com/cr1901/sentinel/blob/csr-break/examples/attosoc.py
<cr1901>
it seems like half the peripherals are nonexistent when using a Rust firmware; accessing the relevant I/O addresses doesn't lock up wishbone, but nothing happens either
<cr1901>
E.g. running "pdm demo -n" prints out "periph/gpio/leds: 0x80000000 to 0x80000001" <-- technically correct
<cr1901>
periph/gpio/inp: 0x80000001 to 0x80000002 <-- not correct (it's actually at 0x800000004
<cr1901>
periph/timer/irq: 0x88000000 to 0x88000001 <-- no idea where this peripheral is; reads from this address don't lock up the bus as would happen on a nonexistent wishbone address, but... the address appears to be returning all 0s (while somehow still performing the correct side effect of clearing the IRQ signal? I need to investigate)
<cr1901>
Tbf, I haven't tested w/ sparse=False, so Idk if I'm using Wishbone2CSR decoder wrong (user error) or I found a bug. Am continuing to investigate.
<cr1901>
(Reads and writes to periph/gpio/* are working correctly)
<cr1901>
(all addresses above are to byte locations)