whitequark changed the topic of #nmigen to: nMigen hardware description language · code https://github.com/nmigen · logs https://libera.irclog.whitequark.org/nmigen
mikolajw has quit [Quit: WeeChat 3.2.1]
peeps[zen] has quit [Quit: Connection reset by peep]
peepsalot has joined #nmigen
<_whitenotifier-d> [nmigen] antonblanchard opened pull request #634: Remove quadratic time complexity in Statement.cast() - https://git.io/Jz91Z
<_whitenotifier-d> [nmigen] codecov[bot] commented on pull request #634: Remove quadratic time complexity in Statement.cast() - https://git.io/Jz9ME
<_whitenotifier-d> [nmigen] codecov[bot] edited a comment on pull request #634: Remove quadratic time complexity in Statement.cast() - https://git.io/Jz9ME
<_whitenotifier-d> [nmigen] codecov[bot] edited a comment on pull request #634: Remove quadratic time complexity in Statement.cast() - https://git.io/Jz9ME
<_whitenotifier-d> [nmigen] codecov[bot] edited a comment on pull request #634: Remove quadratic time complexity in Statement.cast() - https://git.io/Jz9ME
<_whitenotifier-d> [nmigen/nmigen] whitequark pushed 1 commit to master [+0/-0/±1] https://git.io/Jz9DU
<_whitenotifier-d> [nmigen/nmigen] antonblanchard 9f78ac0 - hdl.ast: remove quadratic time complexity in Statement.cast().
<_whitenotifier-d> [nmigen] whitequark closed pull request #634: Remove quadratic time complexity in Statement.cast() - https://git.io/Jz91Z
<_whitenotifier-d> [nmigen/nmigen] github-actions[bot] pushed 1 commit to gh-pages [+0/-0/±13] https://git.io/Jz9DC
<_whitenotifier-d> [nmigen/nmigen] whitequark 98fb3f7 - Deploying to gh-pages from @ 9f78ac0691ef55feda885780f21960e05c7a85a5 🚀
Degi has quit [Ping timeout: 252 seconds]
Degi has joined #nmigen
mcfrdy has quit [*.net *.split]
Qyriad has quit [*.net *.split]
Qyriad has joined #nmigen
mcfrdy has joined #nmigen
gruetzkopf has quit [*.net *.split]
sm2n has quit [*.net *.split]
guan has quit [*.net *.split]
tcal has quit [*.net *.split]
doinkmaster420 has quit [*.net *.split]
d1b2 has quit [*.net *.split]
ebb has quit [*.net *.split]
_whitenotifier-d has quit [*.net *.split]
doinkmaster420 has joined #nmigen
d1b2 has joined #nmigen
tcal has joined #nmigen
guan has joined #nmigen
sm2n has joined #nmigen
ebb has joined #nmigen
gruetzkopf has joined #nmigen
* lkcl waves to whitequark
<lkcl> just looking at PartitionedSignal
<lkcl> ValueCastable doesn't inherit from Value
<lkcl> the plan is to redirect all operations in the same way that python's operator.add(x,y) redirects to x.__add__(y)
<lkcl> for Mux, Assign, Part, Cat, Switch - to __Mux__, __Assign__, __Part__, __Cat__, __Switch__ etc.
<lkcl> (or other suitably-agreed names)
<lkcl> however with ValueCastable not inheriting from Value, the crucial OO context which comes from instantiating an object of type PartitionedSignal - the overriding of those functions - is lost
<lkcl> unless i've missed something
<lkcl> ValueCastable.__new__ is one of the rare obscure bits of python, in 20+ years of using it, that i don't completely understand
<lkcl> if deriving PartitionedSignal from ValueCastable, and PartitionedSignal provides a replacement __add__, replacement __xor__, replacement __Cat__
<lkcl> will PartitionedSignal.__add__ get called as expected
<lkcl> or will Value.__add__ get called which is NOT the desired / expected behaviour?
<lkcl> (UserValue, no problem: it inherits from Value)
<whitequark> ValueCastable is intentionally not derived from Value; this is to avoid breaking user code that derives from it when new methods are added to Value itself
<lkcl> ok - so how can we do exactly that? (override the entire Value API, which will need to be extended to support the desired SIMD-partitioned behaviour)?
<lkcl> the alternative - having to do explicit for-loops duplicating code *four times*, 1x 64 / 2x 32 / 4x 16 / 8x 8, is absolutely out of the question
<lkcl> it would be a total maintenance nightmare
<lkcl> bottom line we have an actual genuine (and becoming increasingly urgent, this is now critical path) need to override the entire Value API.
<lkcl> and to extend the Value API with __Cat__, __Part__, __Assign__, __Switch__, __Mux__
<lkcl> and to override all of those as well
<lkcl> here for example is what PartitionedSignal.__Cat__ needs to do: https://libre-soc.org/3d_gpu/architecture/dynamic_simd/cat/
<lkcl> a preliminary version of that is implemented here:
<lkcl> https://git.libre-soc.org/?p=ieee754fpu.git;a=blob;f=src/ieee754/part_cat/cat.py;h=58aaecf8e768d8b8026691a085a2756cb257344f;hb=88a27fded5ff128f55391c3bb2ea26e9dd6babc2#l90
<lkcl> from what i can see, unless something extremely advanced is done in ValueCastable (dynamic creation of base classes, redirection of functions to a sub-object) it's not going to work
<lkcl> but UserValue will
<vup> lkcl: why do you need inheritance to do that? you can just implement __add__, __radd__, etc on PartitionedSignal
<lkcl> vup: m.if and m.Switch.
<vup> sure, but you can't do those with UserValue either?
<lkcl> if we don't have m.If and m.Switch support, we will be required to rewrite a massive 50,000 lines of code that took over 18 months to write, to use PartitionedSignal.__Mux__
<lkcl> vup, actually, by overriding Value.__Switch__, you can.
<vup> no you can't? No code in nmigen is using Value.__Switch__?
<lkcl> that's because it's part of the proposed changes to add Value.__Switch__, see above
<lkcl> 1 sec
<vup> ok, but you can do that without inheritance?
<lkcl> once ast.Switch(lhs, ....) is replaced with lhs.__Switch__(....)
<lkcl> and once Value.__Switch__ calls the *current* code that comprises ast.Switch
<lkcl> it's overrideable
<lkcl> *without* actually needing to change this
<lkcl> no, not a chance
<lkcl> not without an insane amount of intrusive work
<vup> I mean not really? You can just call lhs.__Switch__ if it exists and ast.Switch if it doesn't
<vup> but anyways, I think I agree with you in that ValueCastable is not really what you want
<lkcl> that's what i meant by "intrusive"
<lkcl> it's an idea - however remember that ast.Switch is used in a number of different places
<lkcl> for m.If _and_ for m.Switch
<vup> i mean sure, but thats all one function
<lkcl> so each instance where it occurs, the exact same duplicated..
<lkcl> 1 sec
<lkcl> ok, what you are suggesting cannot just be applied to ast.Switch
<lkcl> it has to be applied to ast.Cat
<lkcl> ast.Part
<lkcl> ast.Mux
<lkcl> evvverywhere
<lkcl> the entirety of dsl.py and *all* other locations in the code where any ast.* fundamental operation is used
<vup> you don't need it for ast.Part right?
<lkcl> will litter the entire codebase with "if getattr(lhs, __Cat/Part/Mux/Assign/Switch__): ..."
<vup> because that is just generated by Value.{bit,word}_select, and those would be overwritten by PartitionedSignal I assume?
<lkcl> yeeeees of course
<lkcl> 1 sec let me take a look at the implementation of ast.Part
<lkcl> that might be an exception
<lkcl> i'm going to have to think about it
<lkcl> if ast.Part is *100% guaranteed* to *only* call value.bit/word_select and that becomes part of the permanent, final API, then it would work.
<lkcl> however, the idea here is not to make something that's specific to what *we* need
<lkcl> the idea here is to make something that *anyone* might need
<vup> So what I am currently thinking about is why one cannot just put the code to call lhs.__Switch__ inside Switch
<vup> (and similar for Mux and Part)
<lkcl> yes.
<lkcl> that's exactly what's needed.
<lkcl> but it is only stage 1 of 3 stages needed to complete what is needed
<vup> Sure, but this alleviates the need to change it everywhere Cat, Mux, Assign, Switch are used
<lkcl> the 3 stages are:
<lkcl> 1) rename ast.{Something} to {SomethingElse}
<lkcl> 2) add Value.__{Something}__ which calls {SomethingElse}
<lkcl> 3) write the PartitionedSignal.__{Something}__
<lkcl> this preserves the existing behaviour and allows overrides to be performed
<lkcl> so that *not* just us but *anyone* can do same
<lkcl> for example
<lkcl> a ComplexNumberSignal
<lkcl> or
<lkcl> a FixedPointMantissaExponentSignal
<vup> you can do those mostly without what you need
<lkcl> where, obviously, Cat and Part have to...
<vup> but I understand what you are going for
<lkcl> mostly unfortunately isn't good enough when you have 50,000+ lines of existing code
<vup> sure
<lkcl> we've got nearly 2 years of unit tests and Formal Correctness Proofs behind that 50,000+ lines
<lkcl> minimal necessary strategic changes here are critically important
<vup> So as you of course know ValueCastable works by having the user provide a as_value method that converts the *thing* into a Value whenever it is needed (for m.If, Cat, etc.)
<lkcl> we can work with UserValue temporarily
<lkcl> hmmm
<vup> what is preventing you from just returning a subclass of Value in the PartitionedSignal that overrides __Switch__, etc. properly
<lkcl> that's complex to explain
<lkcl> i made a mistake in my initial preliminary analysis, 18 months ago
<lkcl> regarding nested Switch statements
<lkcl> if there is a single Switch statement, and all cases are full of Assigns, there is no "problem"
<vup> (btw I just noticed you probably don't need to hangle Assign, as that is also only generated by Value.eq and with ValueCastable you can just provide you own)
<lkcl> in each partition, when the for-loop per Partition creates a completely separate and individual suite of "SIMD Laned" switch/case statements, the Assign of the HDL could be *replaced* by a word-select
<lkcl> in each partition. there's some pseudo-code explaining it here https://bugs.libre-soc.org/show_bug.cgi?id=458#c9
<lkcl> however
<lkcl> if you have *nested* Switch statements in the HDL, you're screwed.
<lkcl> you actually have to start digging down into the AST to hunt for the Assign leaf-nodes
<lkcl> here i describe a concept where that is done "cleanly" https://bugs.libre-soc.org/show_bug.cgi?id=458#c10
<lkcl> where each HDL Switch actually hunts down for Assign AST and drops the switch/case Conditions *into the Assign node*
<lkcl> now, with that as background / context, i can answer your question
<lkcl> if ValueCastable DESTROYS that information by REPLACING the PartitionedSignal object with an "equivalent" Value [too early], we're screwed
<lkcl> now, i don't know what the ordering is (when the replacement / casting will take place), but it seems overly fragile and a lot of work to analyse
<vup> what is preventing you from attaching all the necessary information you need to the subclass of Value you are returning in as_value?
<lkcl> i.e. if the parsing / processing ordering ever has to change, it could break things that are 3rd party
<lkcl> ... ??? ehn? :)
<lkcl> hang on... are you saying that ValueCastable can itself return an object that derives from Value?
<vup> yeah, I don't see why as_value should not be able to do that
<lkcl> okaaay.
<lkcl> i think that would work
<lkcl> although, ironically, it defeats (bypasses) the intended purpose _of_ ValueCastable, but hey :)
<vup> well kind of
<vup> A clean solution would probably having a new baseclass that has just the "statements" like `Switch, Cat, Mux` which then Value inherits from
<lkcl> hmmm... yeah.
<vup> (and then ValueCastable.as_value would not return a Value, but instead a instance that is / inherits from this baseclass)
<lkcl> if there's a way for abstract base classes (ABCMeta) to declare with a decorator "this function is optional but if you do provide an override it must be the exact same function arguments"
<lkcl> i'd recommend / advocate adding API-declarations to that class for __add__, __xor__, __bool__ etc. etc.
<lkcl> so that people get several messages:
<lkcl> 1) it's possible _to_ override these functions
<lkcl> 2) you don't *have* to override them
<vup> Well I would like to explicitly avoid having these
<lkcl> 3) but if you do, you have to provide the exact same arguments
<lkcl> it was a thought
<vup> because not they might not make sense for everything
<lkcl> indeed.
<vup> and then you have to override the ones that don't make sense and assert or something like that
<vup> and if a new one ever gets added its a breaking change
<lkcl> well, Value already provides them
<vup> its basically the UserValue problem all over again
<lkcl> 1 sec let me see if there's something in ABCMeta like what i mean
<lkcl> which seems puzzling / anomalous.
<lkcl> ABCMeta @abstractmethod *requires* you to override a given function
<lkcl> what i had in mind was conditional: you don't *have* to provide an override, but if you do the *arguments* must be the same
<lkcl> but hey
<lkcl> vup, thank you for the insights. fascinating discussion.
<lkcl> i apologise, i have been sitting down too long and need to get up and walk about
<Chips4Makers[m]> @lkcl: python is in priciple typeless so does not do argument checking. In recent times static typing support has been implemented (e.g. typing module) and the tools like mypy or pylance will do the checks as you describe.
<Chips4Makers[m]> I am most familiar with Pylance in Visual Studio Code and that by default give error when you overload a function in a subclass with incompatile call signature from the parent class.
<whitequark> inheriting from Value is explicitly unsupported
<whitequark> that's the entire reason ValueCastable exists in first place
<vup> whitequark: what do you think about having a new baseclass that provides the lowering of Switch, Cat and Mux, which could then be used to implement custom behaviour for m.If, etc?
<whitequark> unclear if that's something that should be in the core language
<whitequark> adding something like that means that control flow, something very basic and important for understanding the code, will depend not on the control flow construct but on the value being branched on
<whitequark> very few languages have the ability to change how something like `if` works, and for good reason; those which do, do it through macros, and not type-driven
<whitequark> custom lowerings for `If` and `Switch` should be provided by replacing `Module` with a different construct, say `PartitionedModule` (which would probably wrap normal `Module` although there are a few possible ways to do it); then it's always clear, by examining only what's local in the elaborate function, that custom control flow is used
<vup> hmm thats quite a interesting idea
<vup> although of course then you can't make third party code use your custom lowerings
<whitequark> that's a benefit, not a drawback; it means that third party code that wasn't written with your custom lowerings in mind will not be affected by them
<whitequark> (a benefit primarily to third party code authors, that is)
<vup> well I would say it has benefits and drawbacks
<whitequark> well, yes
<whitequark> it has drawbacks for you (the author of the custom lowerings) and benefits for the ecosystem (everyone else)
<vup> sure
<whitequark> ultimately the task of the language designer is balancing conflicting interests like this
<vup> I guess ultimately its still python and you could just monkey patch Module to be what you want :)
emeb has joined #nmigen
<whitequark> sure, and in C++ you can always add a custom preprocessing step for any code you use
<vup> on a more serious note, I wonder if there is some kind of contract for `If` and `Switch` that would limit the drawbacks for the ecosystem
<whitequark> I don't see much of a need to add a way to modify the behavior of `If` and `Switch` when it can be extended by wrapping existing core constructs
<whitequark> adding `PartitionedSignal` isn't just a self-contained extension; it's a language fork. that it looks like a language fork and requires the amount of work a language fork does is, then, completely fine
<vup> well I am still thinking about ways to make it type-driven
<whitequark> well, no, that's not happening
<whitequark> could it be done, technically? sure. is it worth spending language complexity budget? nope
<whitequark> * complexity budget on? nope
<lkcl> Chips4Makers[m], interesting
<lkcl> whitequark, " will depend not on the control flow construct but on the value being branched on" - well, there's "what *should* be done" and there's "mistakes made by someone who failed to observe in the override what should be done"
<lkcl> the first is your responsibility to design
<lkcl> the second most definitely is not
<lkcl> that's the responsibility of the designer of the override
<lkcl> conflating the two and designing the code to *prevent* mistakes when the API and responsibilities are clearly laid out?
<lkcl> we *need* an override of Switch, Cat, Assign, Mux [and probably Part but that's TBD]
<lkcl> it's *our* responsibility to ensure that the overrides conform to the exact and specified and expected behaviour
<lkcl> otherwise, all hell breaks loose.
<whitequark> and it's my responsibility, as the language designer, to make sure that the APIs provided for downstream aren't easy to misuse
<lkcl> and more to the point, 50,000+ lines of *our* code won't work seamlessly
<lkcl> how otherwise would the functionality that we (increasingly urgently) need be achieved?
<whitequark> you're responsible for 50k lines of code. I'm responsible for all of the code already written and all of the code that will be written, so long as we don't do a compatibility break (and I don't think we will any time soon)
<lkcl> (without disruption to either codebase)
<lkcl> yeah a compatibility break would be very disruptive
<lkcl> i'm open to suggestions on how a fully-functioning transparent drop-in replacement for Signal can provide full Mask-Partitionable Dynamic SIMD
<lkcl> where existing "Scalar" (Signal-only) code can be pretty much 95-98% converted with a simple global/search/replace
<lkcl> s/Signal/SomeSIMDClassSignal/g
<whitequark> like I said, what you want is a language fork, and you can get what you want by individually wrapping core language constructs within your codebase
<lkcl> it's not quite that straightforward because the SIMDSignal has to be made aware of the "Mask"
<whitequark> this requires no upstream support at all
<lkcl> ...
<lkcl> but, whitequark, sorry: that's ridiculous. it's basically a fork of nmigen
<lkcl> and a massive amount of work.
<lkcl> replacement for Module
<lkcl> replacement for Value
<whitequark> it's a language fork regardless of whether you admit it or not, purely semantics-wise
<lkcl> no, it really isn't
<lkcl> i spent several months working on this and analysing it.
<whitequark> you're asking me, currently, to make it -look- less like a language fork by adding some hooks upstream just for you
<lkcl> changing the language and changing the semantics is *precisely* and *exactly* what we do not want to do
<lkcl> no, whitequark, i am not
<lkcl> we went over this a few months back.
<lkcl> it was a reasonable and enjoyable conversation in which you agreed, when i mentioned that there are other people who may wish to likewise do similar overrides, that it would be a good ieda
<lkcl> what's changed?
<whitequark> I gave it more thought.
<lkcl> argh, ok.
<lkcl> then you're forcing us into a position of forking nmigen.
<lkcl> and other people will be very unlikely to get the benefit of a general-purpose override for more advanced constructs
<lkcl> such as ComplexNumberSignal
<lkcl> or a GaloisFieldSignal
<lkcl> or FixedWidthFloatingPointSignal
<whitequark> I'm quite happy with this as I don't see this within the scope of the core language
<lkcl> i'm really disappointed to hear that.
<miek> i'm doing complex numbers quite happily right now... i don't need m.If to do funky things
<whitequark> I'm much more interested in enabling people to write things -on top- of the core language rather than -overriding- parts of it
<lkcl> vup: thank you for the discussion and for your consideration. it looks however like we're being forced to create a fork of nmigen.
<vup> I don't think so? why are you ruling out something like `PartitionedModule`?
<lkcl> inheritance of Module is prohibited.
<lkcl> and there is absolutely no need to change even one single line of Module anyway.
<lkcl> that would be precisely the kind of stupid and unnecessary change to the semantics and behaviour of the nmigen HDL core language which is precisely what we do not want and have stated very clearly do not wish to do
<lkcl> i am pissed.
<vup> `del Module.__init_subclass__`, join the dark side :)
<lkcl> we are now forced to put in a hell of a lot of work.
<lkcl> yeah :)
<lkcl> except, there's absolutely no changes to make to Module.
<vup> I mean if you implement everything slightly different you can do it by making changes to `Module` and nothing else (maybe apart from using a custom `Mux` aswell)
<lkcl> vup: there *are* no changes needed to be made to Module, in order to support PartitionedSignal. even doing so implies that there is a language / semantic difference
<lkcl> it would be absolutely disastrous to go there
<vup> But you want a language / semantic difference?
<vup> You clearly want a different lowering of If, Else, Switch
<vup> (doing things in a custom Module might even make things nicer, as you then can keep track of the current active lanes and might not need to walk the ast after the fact actually)
<lkcl> no, we really don't! it's SIMD. you *musn't* change the language
<lkcl> the operation(s) *must* be exactly the same - just on a per-partition basis
<vup> exactly
<vup> but nmigen has no concect of partitions
<lkcl> the language operations *must* be exactly the same
<vup> and making If / Else aware of them imlies changing the language
<lkcl> indeed - and i worked out how it doesn't need to
<lkcl> no!
<lkcl> it really doesn't
<lkcl> it's a parallelisation of the language
<lkcl> not a change *to* the language
<vup> well you clearly have a different concept of *the language* than me
<lkcl> i spent some considerable time working through this
<lkcl> if, add, switch, Cat, these are all high-level language concepts
<lkcl> they're abstract.
<vup> Adding the facilities to do custom type-driven lowering of If, Switch, Cat, etc is in itself a change to the language
<lkcl> they can be applied (singular) or they can be applied (plural)
<lkcl> by "language" i am referring to "the abstract concept of add, If, Switch and so on"
<lkcl> not how they're forcibly and restrictively applied to Value, Signal, Record (etc.)
<lkcl> as a one-to-one and onto (mathematical terms) relationship
<lkcl> don't worry: i get how you need to support whitequark on this.
<lkcl> it just pisses up our already-pressurised timelines to have to maintain a hard fork of nmigen
<lkcl> fricking nuisance
<lkcl> i now have to spend time working out how to maintain parallel hard forks.
<whitequark> they... don't?
<whitequark> I can't imagine a single reason vup -needs- to support me
<lkcl> fortunately, there's something called not-fork https://lumosql.org/src/not-forking/doc/trunk/README.md
<vup> Well in the case of nmigen Module.If, Module.Switch, Cat, etc currently obviously have a more restricted meaning than how you are thinking about them
<vup> (and any language I know has similar restrictions around If, etc)
<lkcl> the team's been working with 3D GPUs, Vector Processors, and so on, now, for over 3 years.
<vup> And this has nothing todo with supporting wq, its all about my (personal) interest in nmigen. I want to find a way around hard forking nmigen
<lkcl> without that experience and knowledge i do Grok that it's hard to appreciate where we're coming from
<lkcl> my feeling is: we need to follow "Show, don't Tell" here
<lkcl> and to keep the diffs to the bare minimum
<lkcl> for practical reasons of having a hard fork, as well as being able to demonstrate minimum disruption.
<lkcl> in a 3D GPU or a Parallel Processor, it is absolutely stupid to conceive of actually changing language behaviour of something as fundamentally basic as an "add" operation or an "if" construct just because you are operating on a batch of elements rather than a single one
<vup> sure, but nmigen is not a 3D GPU or parallel processor dsl, but something more general
<lkcl> we need to use nmigen *to* implement a 3D GPU and a Parallel Vector Processor
<lkcl> where the "usual" way of doing so - massive duplication of identical SIMD code in VHDL or Verilog - we consider to be flat-out insane
<lkcl> i get that if you have 1,000 employees (Intel, NVIDIA) it's a perfectly natural and "obvious" way to do SIMD.
<lkcl> have one contractor write the 1x64 VHDL
<lkcl> have another contractor write the 2x32 VHDL
<lkcl> ...
<lkcl> ...
<tiltmesenpai[m]> I have no clue what you're up to or what your constraints are, but are you unable to make a parameterizable module?
<vup> lkcl: I feel like you are failing to see the midde ground here: using nmigen to build something that is more suited to what you need, for example PartitionedModule and PartitionedSignal
<lkcl> we've already got PartitionedSignal
<vup> tiltmesenpai[m]: its runtime partitioned, so just a parametrizable module doesn't work
<tiltmesenpai[m]> ah I see
<tiltmesenpai[m]> yeah I obviously don't understand what's going on here well enough to give advice lol
<lkcl> however, again: even *starting* a PartitionedModule would send a catastrophic message to our own team and to anyone considering using PartitionedSignal that there is a fundamental low-level change in the semantics
<lkcl> tiltmesenpai[m], it's been 18+ months thought / design work behind this.
<lkcl> we maintain the documentation here: https://libre-soc.org/3d_gpu/architecture/dynamic_simd/
<tiltmesenpai[m]> nope, I was walking in assuming that there's an obvious reason why the obvious solution doesn't work, just wondering what that was
<lkcl> imagine you want to do an implementation of AVX-512 or ARM SVE2
<lkcl> or any other "Maskable" SIMD ALU, in nmigen
<lkcl> you have two choices:
<lkcl> 1) write a implementation of (all) ALUs in (all) pipelines that copes with 1x 64-bit
<lkcl> then write a second (identical, except for a for-loop and for some lengths) implementation that copes with 2x 32-bit
<lkcl> and another that does 4x 16-bit
<vup> I am not going through the semantics argument again, but I don't think communicating PartitionedModule would be so hard that it makes it a impractical choice. Actually clearly documenting PartitionedModule and how if transforms If, Else, etc seems really clean to me
<lkcl> and another that does 8x 8-bit
<lkcl> (you get the idea)
<lkcl> then you have a Switch statement, "if requested 1x64, output that as the result, else if requested 2x32 output that.... etc"
<lkcl> which in gate-count is absolutely awful
<lkcl> or
<lkcl> (2) have the HDL be capable of applying the *EXACT* same constructs that work *PERFECTLY* on single-signals...
<lkcl> preserving those language semantics ***PERFECTLY*** with ***ZERO*** changes ***OF ANY KIND***... to a parallel dynamically-switchable Signal
<lkcl> the only conceptual change - which is what vup and i disagree on (i'm fine with that, btw, vup, no judgement there) - is that those language constructs now apply to *parallel* data, not *single* data
<lkcl> the hard part is getting that Partitioned (SIMD) Signal to change its behaviour at runtime, based on a hidden parameter, called a "Mask"
<tiltmesenpai[m]> wait in the case of 2, what would the gates be doing that's different to 1
<lkcl> amazingly - incredibly - and it's taken 18 months - we worked out how to do it.
<lkcl> a reduction in gate count of about... 200 to 300%
<tiltmesenpai[m]> it seems to me that option 2 would be implemented via a transformation pass that changes things to nested loops via 1, but if you have a different algorithm
<lkcl> the worst case would be a multiplier
* anuejn rust read up on the backlog
<lkcl> yes, exactly. that's precisely what the (minimal) changes are based on: a hidden "loop"
* anuejn has the urgent need to place my opinion on that too - even if it is not relevant
<lkcl> if you had a SIMD multiplier which used technique (1)
<lkcl> you have 12,000 to 15,000 gates for the 64-bit multiplier
<anuejn> i feel that vup and whitequark are right constructs that change if and the likes feel natural in module - since you are explicitly calling m.If
<lkcl> then you have 1/4 of that for a single 32-bit multiplier (call it 3500 gates) but you have two of them in parallel, so that's 7,000 gates
<lkcl> then 3,500 gates for 4x 16-bit
<lkcl> and finally 1,750 gates for 8x 8-bit
<anuejn> I had some quality time wrapping nmigen primitives myself and found it actually quite nice since it does not require a fork of nmigen but you can depend on nmigen and just use your wrappers in downstream code
<lkcl> doing the math - bear in mind that's without the MUXes (the "if partitions == 1x64 elif elif") - that's a total of 27,250 gates
<anuejn> (where ValueCastable was really nice; thanks for that design whitequark)
<lkcl> programmerjake spent about 4 months designing a Partitioned Wallace-Tree Multiplier
<lkcl> which only needs i think 50% more gates than a standard 64-64 multiplier
<anuejn> I also felt the pain in the past that I was wrong when I needed some deeper hooks into nmigen; but after all it is whitequark's job as a good maintainer to say stop when someone wants a really specific extention and balancing interests
<lkcl> anuejn, we worked out the "minimum change point" where the expected behaviour of m.If and m.Switch could be preserved exactly and precisely, and yet made "parallel"
<anuejn> also I think that your feelings are a bit heated lkcl and that it is maybe best to take a step back
<lkcl> anuejn: i feel have a right to be pissed on only just learning now that whitequark's backing out of something that she agreed was perfectly reasonable, about four-five months ago
<lkcl> we now have this urgently on the critical path, and, on raising the discussion to get it implemented, only now find that she's reneged on that.
<lkcl> which places *even more* pressure on our project which is behind by well over a year.
* anuejn thinks: also many things you write are overly specific about the project you are working on and clutter up the lang design discussion which makes it hard for me (and possibly other people as well) to agree with you - as your discussion tactics seem unsound and not contents focused
<lkcl> i went to some trouble to work out the potential other uses to which this could be put
<lkcl> that was part of the discussion four-five months ago.
<miek> i got a very different read on how that discussion ended but ok https://freenode.irclog.whitequark.org/nmigen/2021-05-08#29851286;
<lkcl> not that one, miek
<lkcl> that was even earlier.
<lkcl> i was discussing the implementation details based on the assumption that it had been agreed that the principle was sound (and useful for others)
<lkcl> now that's shot to s***, i'm pissed.
<lkcl> and that's a personal feeling, which i trust i am allowed to express and make clear how disappointed i am
<anuejn> that is your right (always; not only when there is a reason)
<lkcl> i really deeply appreciate you saying that, anuejn
<lkcl> it means a lot
<anuejn> (tho it might not be relevant to people in the channel and they probably dont feel good about you doing so)
<lkcl> appreciate the insight, there.
<tiltmesenpai[m]> yeah, I think there's a difference between "I thought we were going to do x instead of y, and this hurts me" and "you must do x instead of y", and everyone's intentions are just getting mixed up here
<lkcl> yeah, i've never said "it must be done this way [or else]"
<lkcl> i'm just unhappy to learn of unanticipated extra work.
<miek> personally i think it's really unfair to try and load guilt on whitequark for not making the changes you want
<lkcl> it's an Asperger's thing: we don't cope very well with unexpected things
<lkcl> well, that's a very unfortunate reality.
<lkcl> i feel it would be irresponsible of me *not* to point out the ramifications and consequences.
<lkcl> feeling "guilty" - or not - about that isn't my problem: it is how it is.
* lkcl afk. need o get up and walk about
<whitequark> miek: yes, and that kind of approach was why I yielded several months back... I wasn't doing well, and I couldn't really say "no" at the time
<jevinskie[m]> For Altera JTAG primitive use, you have to route altera_reserved_tms/tck/tdi/tdo to the top level module. I can get most of the way there by requesting raw io “-“ but nmigen still tried to create a PIN_altera… constraint in the .qsf. I’ve added a hack to skip the pin in iter_port_constraints_bits() if it has a “VIRTUAL” attribute. Is there a cleaner way to accomplish what I need to do?
<whitequark> can you link to the documentation for the primitive you're using?
<whitequark> does it just... use reserved names?
<jevinskie[m]> Undocumented but this is how it uses it: https://gist.github.com/jevinskie/811a4fd6deba7fff7280f6908ae37437
<jevinskie[m]> Yes the altera_reserved* are reserved signal names by quartus
<whitequark> how does your board file look like?
<jevinskie[m]> Using an unmodified DECA platform from nmigen-boards
<whitequark> okay, that's cursed
<whitequark> I think you don't need the pins to go through Platform at all
<whitequark> only the `ports` part
<lkcl> that is a shame. there are a lot of people and project riding on this evolution of nmigen.
bvernoux has joined #nmigen
emeb has quit [Ping timeout: 245 seconds]
emeb has joined #nmigen
mikolajw has joined #nmigen
XgF has quit [Remote host closed the connection]
XgF has joined #nmigen
bvernoux has quit [Quit: Leaving]
hell has quit [Quit: CPU triple-faulted.]
electronic_eel has quit [Remote host closed the connection]
sauce has quit [Remote host closed the connection]
sauce has joined #nmigen
electronic_eel has joined #nmigen
hell has joined #nmigen
<jevinskie[m]> whitequark: that works for cli.main() (I was just using that for test generation) but I can’t find any means to extra pass pins into platform.build() as is used by my real SoC script with a board def
mikolajw has quit [Quit: WeeChat 3.2.1]
Chips4Makers[m] has quit [Ping timeout: 246 seconds]
cesar has quit [Ping timeout: 264 seconds]
Niklas[m] has quit [Ping timeout: 264 seconds]
kaji has quit [Ping timeout: 264 seconds]
emilazy has quit [Ping timeout: 264 seconds]
Chips4Makers[m] has joined #nmigen
emeb_mac has joined #nmigen
cesar has joined #nmigen
Niklas[m] has joined #nmigen
lf has quit [Ping timeout: 250 seconds]
lf has joined #nmigen
kaji has joined #nmigen
emilazy has joined #nmigen