<Wanda[cis]>
this is actually why I'd rather not have any backends that are not based on prjcombine; having a unified database format is a core part of the plan
<leocassarani[m]>
Yeah, makes complete sense
<Wanda[cis]>
after the Xilinx saga and the current (unpublished) siliconblue work, I'm reasonably confident prjcombine can deal with pretty much anything we'd want to include
<Wanda[cis]>
(that and also I've looked into Gowin and other Lattice devices closely enough to be reasonably sure it won't be a problem)
<Wanda[cis]>
anyway. possibly the most core issue we want to fix with nextpnr is that it's a separate tool at all, with a separate IR and all it implies.
<Wanda[cis]>
having an integrated toolchain allows you to do things that are simply not possible with separate synthesis and P&R tools
<Wanda[cis]>
like, say, resynthesis. pick the area that failed timing, and apply some extra-strength expensive optimizations to it post-factum.
<leocassarani[m]>
Yeah and potentially much better diagnostics? Whenever my design fails timing it's a bit of a nightmare figuring out exactly why (relating it back to the Verilog)
<Wanda[cis]>
oh that's kind of a yosys problem actually
<Wanda[cis]>
it... does an absolute mess of naming cells
<leocassarani[m]>
Yes I've noticed :D
<Wanda[cis]>
RTLIL has this fascinating property
<Wanda[cis]>
every cell and wire has to have a name. exactly one.
<Wanda[cis]>
of course, there is not really meaningful name to pick when you're in the middle of some advanced logic optimization pass that makes a complete hash out of the original netlist, and writing yosys passes is hard enough without having to worry about naming every individual cell you emit, so in practice the stuff that ends up in the name is an absolute incomprehensible mess.
<Wanda[cis]>
the abc mapper basically just nukes names and assigns completely random ones later.
<Wanda[cis]>
the very first thing we did when designing prjunnamed IR is throwing out the names and just identifying every single cell by its position in the netlist. by which I mean a literal index within the array.
<Wanda[cis]>
and we just got rid of wires entirely.
<Wanda[cis]>
hence the project name.
<leocassarani[m]>
oh that had completely escaped me
<Wanda[cis]>
names are powerful things, and they are to be assigned with intent.
<Wanda[cis]>
we just treat them as separate things that can be attached to cells or values. or not. or maybe you can attach several distinct names to a cell, because of aliasing.
<leocassarani[m]>
So your IR is in the netlist crate, right?
<Wanda[cis]>
correct
<Wanda[cis]>
we believe the set of cells we have is reasonably good, and won't change all that much
<Wanda[cis]>
(well we want to add print cells and assert cells and some other stuff like NIR has, but the core synthesizable cells are there)
<Wanda[cis]>
however, we haven't implemented a proper metadata system yet
<Wanda[cis]>
which is also planned to be a core part of the IR
<Wanda[cis]>
stuff like source locations, scope information, and proper hierarchical names
<leocassarani[m]>
Yeah, looks really interesting so far
<leocassarani[m]>
Thanks for explaining it all, it's very exciting
<Wanda[cis]>
you're welcome
<Wanda[cis]>
heh
<Wanda[cis]>
it's nice to finally put down this stuff in writing
<Wanda[cis]>
that project has just been in my and Cat's heads for like 3 years
<widlarizerEmilJT>
<Wanda[cis]> "hence the project name." <- Ohhhhh.
galibert[m] has joined #prjunnamed
<galibert[m]>
Are you interested in eventually supporting cyclone V, and if yes, what should it look like? I'd like to help converting the information I plonked in mistral into however you'd like it to be
<Wanda[cis]>
cyclone V and altera in general is very much in-scope, eventually
<Wanda[cis]>
and I'd like to implement that by writing a proper Quartus backend for prjcombine, and reversing every single device altera ever made in one fell swoop
<galibert[m]>
should stuff go into prjcombine?
<Wanda[cis]>
but also
<Wanda[cis]>
right now we are not that interested in having altera as a target
<galibert[m]>
heh
<Wanda[cis]>
we're only interested in particular targets right now as a tool to validate the core flow actually works
<Wanda[cis]>
siliconblue has always been the obvious place to start. the second obvious target is xilinx, particularly given the nice database I have laying around
<Wanda[cis]>
these two should give us more than enough things to work on
<galibert[m]>
some peculiarities of quartus: they have to backends for timing. One does a proper model of wires, capacities and stuff and uses step integration to compute the actual voltage change shapes and extracts timings from that (quartus_sta). The other has gigantic times of timings for every wire and is used for P&R
<galibert[m]>
gigantic tables that is
<Wanda[cis]>
however. there is another major problem that makes us very uneasy with implementing xilinx or altera support.
<galibert[m]>
cranky lawyers?
<Wanda[cis]>
no, worse
<Wanda[cis]>
consider what happens to this project the second it becomes known we have full xilinx flow.
<galibert[m]>
I'd suspect the answer is "nothing much" unless vivado is really expensive?
<galibert[m]>
quartus for cyclone v is free
<Wanda[cis]>
have you seen the shit people will put up with to get open-source xilinx flows?
<galibert[m]>
I haven't, is it bad?
<Wanda[cis]>
symbiflow. prjxray.
<Wanda[cis]>
right now prjunnamed, if we were to get P&R and finish synthesis for siliconblue, is just a funny alternative to the existing established yosys toolchain, and when things don't work we just say it's experimental and people come back a few months later or something
<Wanda[cis]>
if we were to get P&R for xilinx, prjunnamed would instantly become *the* highest-quality open-source toolchain for a bunch of devices
<galibert[m]>
and it's a little early for that?
<Wanda[cis]>
yes
<galibert[m]>
I'd say nobody cares about cyclone V except there's mister and analogue pocket
<galibert[m]>
so open source people with the associated... enthusiasm
<galibert[m]>
do you use a specific devboard for sb testing?
<Wanda[cis]>
this is one of these questions that matters not one bit
<whitequark[cis]>
i just grab something out of the pile of boards we have
<whitequark[cis]>
and a pile of rtl i have
<whitequark[cis]>
a mature toolchain shouldn't be tied to a singular device
<Wanda[cis]>
by the way, one of the reasons I've always disliked so many open-source reversing projects is the weird focus on particular devices.
<whitequark[cis]>
so we might as well could start on that from the beginning
<galibert[m]>
ah ok :-) I don't have a pile of boards, at least not ice* ones
<Wanda[cis]>
this is actually a core design principle of prjcombine
<whitequark[cis]>
i have several dozen boards. i don't even remember all of them
<whitequark[cis]>
i can borrow a kintex ultrascale also
<Wanda[cis]>
make this stuff capable and automated enough that it'll just blow straight through the entire device list
<whitequark[cis]>
thats the highest one ive touched
<Wanda[cis]>
and it worked. the prjcombine support list starts at XC2000 and ends at Virtex 7.
<galibert[m]>
Not sure how one automate RE-ing the bitstream format
<Wanda[cis]>
yes.
<whitequark[cis]>
that's fairly straightforward?
<galibert[m]>
(framing, checksums, all that stuff)
<whitequark[cis]>
oh, that
<galibert[m]>
(compression too)
<Wanda[cis]>
oh, you don't automate all of it
<galibert[m]>
ok then
<whitequark[cis]>
that doesn't vary too much between devices
<Wanda[cis]>
you just make a framework that makes it easy
<galibert[m]>
it varies quite a lot from an altera device series to another for some reason
<galibert[m]>
I mean from cyclone V to IV to X, etc
<galibert[m]>
not withing cyclone V of course
<galibert[m]>
s/withing/within/
<Wanda[cis]>
but also, about the ice40 board
<Wanda[cis]>
there is actually one that we'd be particularly interested in supporting
<Wanda[cis]>
you may have heard of it
<galibert[m]>
glasgow? ;-)
<Wanda[cis]>
mhm
<galibert[m]>
As it happens I have one just there connected to various points into a yamaha mu100b
<widlarizerEmilJT>
Any plans for managing passes?
<Wanda[cis]>
you'd have to be a little more specific
<whitequark[cis]>
i feel like we should be offering our users the same amount of managing passes as, say, clang
<whitequark[cis]>
which is to say that most people should not even think about it
<widlarizerEmilJT>
I guess I'm interested in what you think about user-customizing flows vs baking a happy path
<Wanda[cis]>
oh that.
<Wanda[cis]>
yes, then I believe Cat put it into words very well
<whitequark[cis]>
i'm actually fairly comfortable saying "if you want to customize the flow build it from source" although we'll eventually have some sort of extension language one way or another
<whitequark[cis]>
of course we'll still have like, target options.
<Wanda[cis]>
I consider yosys exposing its guts at the slightest provocation to be one of its worst design features
<Wanda[cis]>
exhibitionist software design
<galibert[m]>
it would be nice at some future point to have all of it as a python library you could import in a amaranth program
<Wanda[cis]>
it results in no clear delineation of what is the public API and what is not, resulting in it being absolutely not possible to change anything for the fear of breaking something somewhere
<Wanda[cis]>
galibert[m]: to have what as a python library?
<Wanda[cis]>
prjunnamed, from amaranth standpoint, is a box you put netlists into and bitstreams come out
<galibert[m]>
a bit like exec() without temporary files
<Wanda[cis]>
we have the platform stuff for that, yeah
<Wanda[cis]>
I really don't know what you're asking for here
<galibert[m]>
don't worry, I'm not 100% sure I know either
<Wanda[cis]>
we do have the platform framework that manages running toolchains for you; this applies to all of yosys+nextpnr, icecube, vivado, ...
<galibert[m]>
just ignore me at this point :-)
<Wanda[cis]>
and it will equally apply to unnamed
<Wanda[cis]>
<Wanda[cis]> "I consider yosys exposing its..." <- anyway, I want to expand on this a little more
<Wanda[cis]>
there are several problems with the yosys design here
<Wanda[cis]>
exposing an interface like that has a cost
<Wanda[cis]>
the problem with yosys is that it, in many ways, encourages you to meddle with passes
<Wanda[cis]>
you already have to write a yosys script to do anything useful; the direct interface to the passes is the exact same interface you use to run synth_ice40
<Wanda[cis]>
and yosys is quite proud of it too, encouraging you to hack up random scripts to hack on the IR
<Wanda[cis]>
now. the cost. it is twofold
<Wanda[cis]>
first, it exposes RTLIL internals and pass characteristics as a public or semi-public interface, setting them in stone and preventing you from improving it
<Wanda[cis]>
hence stuff like $mem*_v2 cells where I went to considerable amount of effort to maintain some compatibility because we could not have any idea who is actually using the raw cell interface
<Wanda[cis]>
second, passes in yosys have input invariants which they do not enforce. you can very easily shoot yourself in the foot by eg. running a wrong pass on a netlist with processes.
<widlarizerEmilJT>
you mean users outside of the yosys upstream or within it?
<Wanda[cis]>
outside of yosys upstream.
<widlarizerEmilJT>
Yep
<Wanda[cis]>
so. the two costs.
<widlarizerEmilJT>
the invariants are a particular PITA
<Wanda[cis]>
they are not too much of a concern for a debugging interface
<Wanda[cis]>
maybe we should have something like that. for clang you can do -emit-llvm and go to town with the opt command.
<Wanda[cis]>
but there must be a clear delineation of public and private APIs.
<galibert[m]>
plus sane people would like to just do fpgac --target whatever design.v -o design.bin and not weird scripts
<Wanda[cis]>
between stuff we commit to supporting, and stuff we will just break whenever it's convenient.
<Wanda[cis]>
galibert[m]: yes. this is the interface we want.
<galibert[m]>
heh, you're sane
<widlarizerEmilJT>
Wanda[cis]: I would like that to be the case with prjunnamed as well. Though with clang, the method of breaking down the automatic full flow to component calls with saving intermediates actually isn't transparent. So there's space for improvement for even better experimentation
<Wanda[cis]>
well, it's going to be a little more complex because you want to look at timing reports and whatnot, but still. this is the focus point.
<whitequark[cis]>
clang's pass manager is a notorious nightmare
<whitequark[cis]>
i'd like to avoid having that
<widlarizerEmilJT>
can you elaborate?
<widlarizerEmilJT>
or link to resources etc
<whitequark[cis]>
remember chandlerc converting everything to the new pass manager for close to a decade?
<widlarizerEmilJT>
Uh, I don't. I'm a late arrival to compilers
<widlarizerEmilJT>
I'm aware of there being two though
<whitequark[cis]>
ok, well, that happened
<whitequark[cis]>
if that alone doesn't tell you there are issues with the pass manager i don't know what to say
<whitequark[cis]>
basically, pass ordering is more of a dark art than a science, and managing pass dependencies is extremely challenging
<whitequark[cis]>
the less configurability we have in that part of the flow, the better
<widlarizerEmilJT>
Kind of a gap between "there are issues" and "this is a nightmare", I assume everything has issues
<whitequark[cis]>
any refactoring that goes on for more than five years is definitionally a nighmare
<whitequark[cis]>
s/nighmare/nightmare/
<whitequark[cis]>
although configurability didn't cause that part
<whitequark[cis]>
like... a pass manager is basically a mini-build-system which has the additional unpleasant property where the thing that is being built is continuously clobbered
<whitequark[cis]>
and it has to track invalidation of dependencies regardless
<whitequark[cis]>
i don't want to work on that!
<widlarizerEmilJT>
got it
<Wanda[cis]>
oh, and to be clear, I consider this one of the worst design failings in yosys is because it locks everything else into place.
<Wanda[cis]>
during my time at yosyshq I was more than willing enough to transform RTLIL, over time, into something more reasonable
<Wanda[cis]>
the weird init attribute thing? I could just lock myself in a cave for a week and exorcise it from the entire codebase
<Wanda[cis]>
but exposing so many implementation details is what made it impossible
<Wanda[cis]>
well. that and Claire being.... resistant to change
<Wanda[cis]>
so what I did instead is make many overlays over RTLIL instead, that look like the IR that should have been
<Wanda[cis]>
things like kernel/ff.cc or kernel/mem.cc, or SigMap (though that one's not on me)
<Wanda[cis]>
but this has always been a massive pain to deal with
<widlarizerEmilJT>
If the flow of passes is restricted to require less dependency and invariant modeling, I wonder what this means for alternate flows in the future - formal and ASIC. I mean if there's 3 restricted flows built into the tool rather than an undefined subset of a combinational explosion of then that's still productive and maintainable
<Wanda[cis]>
in many ways, there's a much simpler IR in yosys that's struggling to get out
<Wanda[cis]>
in fact, you'll note the strong similarity between unnamed FlipFlop cell and what I made ages ago in kernel/ff.cc
<widlarizerEmilJT>
Wanda[cis]: Yeah I'm writing yet another pass that is almost purely poking at your ff interface
<Wanda[cis]>
(it's going to be even more similar when we actually add latches to the model)
<Wanda[cis]>
(just. Cat kinda made me descope latches. in no small part because iCE40 doesn't have them.)
<whitequark[cis]>
i think we probably don't want to have a formal flow
<whitequark[cis]>
I've been talking to Jannis and most likely the way to go here is to use imctk once it's ready
<whitequark[cis]>
we can of course add export/import support but besides that, synthesizers are not actually very good at formal verification
<whitequark[cis]>
i'm not even sure if we should be processing decision trees, i already take advantage of X-prop there...
<Wanda[cis]>
there's some value that unnamed can provide here once we have an elaboration story and actual frontends; but that'd not include the actual synthesis part, just using the common IR as a funnel
<galibert[m]>
feels like an error number collision?
<mei[m]>
doesn't feel like something that'd happen?
<mei[m]>
i think it wants to exec a sat solver
<galibert[m]>
ohhh. Lemme strace it
<mei[m]>
go and install z3
<galibert[m]>
looks like I need to do a full update, gonna take a little while
<galibert[m]>
fwiw, strace agrees with you, it's z3 that's missing
<mei[m]>
oh hey, it's even written down in the README
<mei[m]>
nice
<galibert[m]>
and I missed it, sorry about that
<mei[m]>
dw
<galibert[m]>
yay, all tests passed
<mei[m]>
ChangeQueue::unalived_cells? c'mon
<mei[m]>
do you not have the balls to call it murdered_cells?
<mei[m]>
what's the difference between Cell and CellRepr?
<mei[m]>
also Value vs Net? is a Net always one bit wide?
<Wanda[cis]>
Net is one bit; Value is a list of nets
<Wanda[cis]>
Cell is the conceptual model; CellRepr is something we actually store in-memory for efficient storage of fine netlists (ie. netlists where most stuff is 1-bit-wide gates)
<Wanda[cis]>
it's... not clear it's actually worth it
<Wanda[cis]>
it came up in the past
<mei[m]>
i read the entire available history of the channel but i might have missed it
<mei[m]>
element scrolling can be wonky at times
<Wanda[cis]>
oh, no
<Wanda[cis]>
it's come up in previous discussions in like 2021
<mei[m]>
<Wanda[cis]> "it's... not clear it's actually..." <- might make more sense to like, intern the values or something
<mei[m]>
make em indices into a flat Vec<u32> under the hood
<Wanda[cis]>
yeah uh.
<Wanda[cis]>
tbh the memory representation thing is a bit of a reaction to some old yosys discussion
<Wanda[cis]>
I'd rather not worry too much about memory efficiency just yet
<mei[m]>
so, you have this split for now, to make sure that you don't design yourselves into a corner where it's hard to introduce, in case you decide that it's a good idea
<mei[m]>
so, a Net is just an index into Design::cells?
<mei[m]>
oooh, that's what the Skip cell is for
<Wanda[cis]>
yeah
<Wanda[cis]>
it... may be on the "overly clever" side
<mei[m]>
yeahh, it kinda feels like a lot of the savings of being able to refer to a particular bit in only 4 bytes is gonna be eaten up by all the Skips lol
<mei[m]>
but this should be refactorable later with benchmarks to guide us
<Wanda[cis]>
I'm more worried about all the allocations than about skips
<mei[m]>
yeah
<Wanda[cis]>
anyway. you may be interested in the other alternative, which was implemented in amaranth NIR.
<Wanda[cis]>
the difference is pretty simple; a net is a (cell index, bit index) tuple, and there's no skip stuff
<Wanda[cis]>
the reason we switched to the current version is because we were concerned about efficient representation of fine netlists, ie. netlists made mostly from individual gates
<Wanda[cis]>
if you have such a netlist, there's basically no skips, the CellRepr short format is used so there's no allocations
<Wanda[cis]>
it's close to optimal
<mei[m]>
right, a lot of the compute-intensive parts are being done on the fine netlists
<Wanda[cis]>
that is the idea, yes
<Wanda[cis]>
there's a bit of a problem with this plan because we don't represent LUTs all that well
<mei[m]>
oh. oooohhh
<mei[m]>
Vec<Trit>
<mei[m]>
ouch
<mei[m]>
yeah, but this is just low hanging fruits for perf work later on
<mei[m]>
this is fine
<Wanda[cis]>
if you try to design a tight compressed ternary representation for this shit I'm going to personally murder you.
<Wanda[cis]>
but. yeah. this is stuff that can be improved later on.
<Wanda[cis]>
we do have the capability for compression
<mei[m]>
Wanda[cis]: kinky
<mei[m]>
i was thinking more of a pair of bitvec who love each other very much kind of vibe
<Wanda[cis]>
oh we were thinking of something else
<Wanda[cis]>
`Either<Vec<Trit>, (u64, u64)>` is same size as `Vec<Trit>`
<Wanda[cis]>
and the pair of u64 is enough to encode consts up to 64-trit
<Wanda[cis]>
... without doing weird compression stuff to pack 80-something trits, mind you.
<Wanda[cis]>
I may have yosys trauma.
<mei[m]>
who the fuck would do arithmetic coding for an in-memory representation
<Wanda[cis]>
uhh.
<mei[m]>
you're supposed to be doing computation with this
<Wanda[cis]>
well.
<mei[m]>
were they on drugs when they designed this
<Wanda[cis]>
... I mean.
<mei[m]>
so, what are the semantics of Trit::Undef, exactly?
<Wanda[cis]>
excellent question!
<Wanda[cis]>
basically something like Verilog X until decided otherwise
<Wanda[cis]>
also similar to LLVM undef in that you can substitute it with anything you want, including with a value that magically appears to be different each time you look at it
<mei[m]>
(this question is motivated by seeing Trit::mux)
<Wanda[cis]>
ie. you're allowed to optimize a = undef; b = a xor a to b = 1 if you'd like
<Wanda[cis]>
so. this is the bit where we're going to need tighter definition to not fuck this up in subtle ways.
<Wanda[cis]>
Trit::mux is exactly Verilog's ?: operator semantics
<Wanda[cis]>
I think it's reasonably good
<Wanda[cis]>
but there's less obvious stuff
<mei[m]>
so X in verilog is kind of like unreachable_unchecked?
<Wanda[cis]>
not quite
<Wanda[cis]>
X is not a value that instantly disintegrates your circuit when it appears somewhere
<Wanda[cis]>
materializing it is perfectly okay
<Wanda[cis]>
it just happens to poison everything downstream with itself, until it's gated off
<Wanda[cis]>
ie. mux(1, 0, X) just selects the 0 and doesn't let the X propagate further
<mei[m]>
i feel like the existence of X can lead to a lot of subtly incorrect optimizations
<Wanda[cis]>
X kind of means "just stuff whatever is convenient to minimize the circuit here, I'm not going to use it"
<Wanda[cis]>
yes.
<Wanda[cis]>
it's a dangerous tool
<mei[m]>
convenient how prjunnamed_smt2 just seems to bail on any mention of X
<Wanda[cis]>
that's because it's kinda MVP-grade
<Wanda[cis]>
we need X-aware smt2
<Wanda[cis]>
and for that we need well-defined semantics
<Wanda[cis]>
but, this stuff has been done previously in yosys, in not completely horrible ways
<Wanda[cis]>
I mean, the X-aware smt2, not the well-defined semantics
<Wanda[cis]>
I've also wondered if we're going to need basically two subtly different variants of cells to ensure the X propagation rules don't fuck us over
<Wanda[cis]>
consider the adc cell
<Wanda[cis]>
the approach I have (a little implicitly, but it's codified in the const-eval code) picked for unnamed is that an X input at bit position a makes all output positions from a upwards undefined
<Wanda[cis]>
it's not the only definition possible
<Wanda[cis]>
Verilog uses a different decision here: if any input bit is X, all output is X
<Wanda[cis]>
which is inconvenient because it means you cannot merge a[7:0] + b[7:0] and a[3:0] + b[3:0] into a single adder. an X input at a[4] would wrongly poison the lower bits.
<Wanda[cis]>
(enabling this optimization is what motivated my reasoning)
<Wanda[cis]>
you could also go into a little more detail, and think of the adc as a series of XOR3 + MAJ3 gates (or, full adders, if you'd prefer), and stop X propagation through the carry chain at the points where the other MAJ3 inputs are both 0 or both 1
<Wanda[cis]>
but I'm not convinced there's any useful optimizations that this enables, so meh
<galibert[m]>
what is X useful for?
<Wanda[cis]>
galibert: for letting the synthesizer know you don't care about values of some signals in some branches
<Wanda[cis]>
consider an instruction decoder driving control signals to an ALU
<Wanda[cis]>
what do you send there when you're processing an instruction that doesn't touch the ALU?
<galibert[m]>
so you're delegating that decision to the compiler
<galibert[m]>
nice
<Wanda[cis]>
the obvious answer is X, which allows the synthesizer to simplify the decision trees and send whatever garbage is convenient
<galibert[m]>
amaranth doesn't have X at this point, right?
<Wanda[cis]>
nope
<Wanda[cis]>
Amaranth design is centered around not letting you fuck yourself over too easily
<Wanda[cis]>
X can be an incredibly dangerous tool
<galibert[m]>
which is nice, honestly
<Wanda[cis]>
it is not quite as bad as undefined behavior in C, but it's the same kind of thing
<galibert[m]>
in theory the compiler could find out that a signal is not important in a given context, but I guess that's yet another thing that's NP-annoying
<Wanda[cis]>
mind you, there have been discussions about including undefined values in Amaranth
<Wanda[cis]>
but they were centered around the one place where they're very hard to avoid
<Wanda[cis]>
which is memory initialization in ASICs
<galibert[m]>
for non-initialization of srams?
<Wanda[cis]>
which is... well, not a thing
<galibert[m]>
yeah
<galibert[m]>
it's more of a sim issue though
<galibert[m]>
the sram case
<Wanda[cis]>
Amaranth requires all memories to have well-defined initial values; usually (though not always) trivial to implement in FPGAs given that they're loaded together with the bitstream, pretty much impossible in an ASIC
<Wanda[cis]>
now, about sim
<Wanda[cis]>
X values are kind of very annoying to deal with in simulation
<Wanda[cis]>
particularly when it's based on sequential processes, not netlists
<galibert[m]>
they're supposed to behave like a non-fully-viral NaN, is a way? like a and 0 should still give 0?
<Wanda[cis]>
consider: what happens when you have an if (a) begin [...] end; in Verilog and a happens to be X?
<galibert[m]>
urgh
<Wanda[cis]>
galibert[m]: basically yes
<galibert[m]>
the if case sounds terrifying
<Wanda[cis]>
Wanda[cis]: according to the Verilog standard, the answer to this question is "`if (a)` executes iff `a` is 1, so it does not execute when it is `X`"
<galibert[m]>
that's a Bad answer
<Wanda[cis]>
this results in the entire Verilog simulation model being essentially garbage that's not fit for purpose when X is involved, yes.
<Wanda[cis]>
it results in simulation-synthesis mismatch of the bad knd
<Wanda[cis]>
ie. simulation claims you get a well-defined value, while the hardware will just do something completely different.
<galibert[m]>
you'd better scribble X everywhere in that case, that's less traumatic
<galibert[m]>
the "it's fucked" would be way more obvious
<Wanda[cis]>
you'd better scribble X everywhere that the relevant branch touches, yes
<Wanda[cis]>
but Verilog cannot specify that behavior
<galibert[m]>
Verilog is Bad, news at 11
<Wanda[cis]>
because Verilog is not a synthesizable language in the general case
<Wanda[cis]>
consider: it has loops.
<mei[m]>
because verilog can printf?
<Wanda[cis]>
and, yeah, stuff like printf
<Wanda[cis]>
or rather, $display
<mei[m]>
it'd be funny if you did a printf in an if(a) when a happens to be an X and it just printed a bunch of X's to the terminal
<Wanda[cis]>
should set the oldschool blink attribute
<mei[m]>
<3
<galibert[m]>
well, loops on scalar, netlist-constant data makes perfect sense, we do that all the time in amaranth. But I guess you're not talking about that, right?
<Wanda[cis]>
mhm
<galibert[m]>
that's what I was afraid of
<Wanda[cis]>
Verilog mixes simulation-only models with synthesizable stuff with no clear delineation
<galibert[m]>
and some stuff that doesn't even make sense in simulation, it feels like at times
<Wanda[cis]>
you can actually just inspect the value and check it for X
<Wanda[cis]>
it has two equality operators
<Wanda[cis]>
== which gives you an X if there are X inputs involved and the result isn't obviously unequal on other bit positions
<galibert[m]>
only two? We know worse :-)
<Wanda[cis]>
and === which does a literal comparison that includes matching X to X only, and always returns 1 or 0
<Wanda[cis]>
galibert[m]: don't worry, SystemVerilog added more
<galibert[m]>
How reassuring
<Wanda[cis]>
funnily enough, RTLIL actually has separate cells for the two! what for, I do not know
<Wanda[cis]>
maybe formal.
<galibert[m]>
is your IR RTLIR with the bad parts removed or something completely different?
<Wanda[cis]>
it's actually derived from Amaranth NIR
<Wanda[cis]>
which is in turn derived from Amaranth HDL
<Wanda[cis]>
... which, in turn, was somewhat influenced by yosys, yes
<galibert[m]>
standing on the shoulders of... [insert noun here]
<Wanda[cis]>
it is influenced by RTLIL, it'd be a lie to pretend otherwise
<Wanda[cis]>
Amaranth doesn't exist in a vacuum and lowering to RTLIL was a consideration when we were designing NIR
<galibert[m]>
not everything is bad in rtlir, far from that
<Wanda[cis]>
that said, we trimmed it quite aggressively
<galibert[m]>
oh it's rtlil, not r?
<Wanda[cis]>
it's very much rtlil
<galibert[m]>
language, not representation I guess
<Wanda[cis]>
anyway. our focus was on removing much of the redundancy that exists, so the passes don't have to consider a myriad ways of expressing the same thing
<galibert[m]>
that's nice
<Wanda[cis]>
eg. you'll note that we only have `==`, signed `<`, and unsigned `<` comparison operators
<Wanda[cis]>
I'm actually still considering getting rid of the or cell
<Wanda[cis]>
maybe I'll do it
<galibert[m]>
why?
<Wanda[cis]>
redundant
<galibert[m]>
not and not is kind of busy
<Wanda[cis]>
a little, yes
<Wanda[cis]>
but inverters are trivial to fold
<galibert[m]>
you want to keep some readability for the poor humans trying to debug stuff
<Wanda[cis]>
and it reduces the number of rules we have to add
<Wanda[cis]>
it's not like I invented the concept, either; AIGs are a thing after all
<galibert[m]>
google is only answering insurance stuff when I put in AIG?
<Wanda[cis]>
and-inverter graph
<galibert[m]>
the splitting of xor isn't annoying in AIGs?
<Wanda[cis]>
it's a representation commonly used for logic optimization
<Wanda[cis]>
well yeah
<Wanda[cis]>
that's why XAIGs are a thing too
<Wanda[cis]>
and why I'm not proposing to get rid of xor
<galibert[m]>
yeah, I remember some proof systems added xor because removing it is combinatorially annoying, especially when you play with crypto computations
<Wanda[cis]>
xor is a distinct thing that's useful to consider on its own merits; or is just an evil mirror twin of and
<Wanda[cis]>
a few days ago I called or an "and under CPT symmetry" and Cat hissed at me and told me to go to sleep.
<galibert[m]>
she had a correct reaction
<mei[m]>
Wanda[cis]: badeline!!
<Wanda[cis]>
.... mei
<mei[m]>
mirror mommy
<Wanda[cis]>
mei.
<Wanda[cis]>
well luckily for you you're out of biting range right now
<mei[m]>
...exactly what i was typing
<galibert[m]>
Now I'm wondering what happens when a LUT beta-decays, and that's all your fault
<Wanda[cis]>
galibert[m]: now that sounds like a kind of area-recovery optimization I'll have to implement or something
<Wanda[cis]>
<Wanda[cis]> "consider the adc cell" <- oh, and I didn't finish that thought
<Wanda[cis]>
so there's a problem with our adc cell: when you're emiting Verilog, you actually cannot legally emit it as a + operator because of the incompatible X semantics
<Wanda[cis]>
on the other hand, our X semantics is useful for optimization
<Wanda[cis]>
so, what, do? one option I've previously considered is to have subtly different flavors of some cells that differ in what exact X propagation rules they promise/require
<galibert[m]>
urgh
<Wanda[cis]>
adc is one such cell; shifts are another
<galibert[m]>
that's going to cause some many subtle bugs
<Wanda[cis]>
shifts are particularly interesting because, aside of X semantics, they're a little bit equivalent to binary tree multiplexers
<Wanda[cis]>
so my original IR draft from two years ago had variants.
<mei[m]>
how about: if emitting verilog, freeze all the X's to 0
<Wanda[cis]>
won't help you because you can get X on primary inputs
<Wanda[cis]>
X is a fact of life. even in hardware.
<mei[m]>
how come?
<Wanda[cis]>
consider: there is no such thing as digital logic
<mei[m]>
okay but that doesn't actually map to your X does it
<galibert[m]>
fpga like to pretend there is though
<Wanda[cis]>
what do you think happens when you have an input that's halfway between GND and VCCIO?
<Wanda[cis]>
you get some garbage that will propagate until it's properly gated off
<Wanda[cis]>
it's an X.
<mei[m]>
it does look like an X
<mei[m]>
but it isn't really much of a controlled process is it
<galibert[m]>
it's not a X, it's a whyyyyyyyyyyyyyyyyyyyyy?
<galibert[m]>
(sorry)
<Wanda[cis]>
it operates on the same rules
<Wanda[cis]>
ANDing that shit with 0 will still get rid of it
<mei[m]>
i have no experience with this but i would assume that you can't actually promise anything about what happens if the input pin is an X?
<mei[m]>
Wanda[cis]: okay but LUT4'ing where the lut bits happen to align into an and?
<Wanda[cis]>
interesting question, isn't it
<Wanda[cis]>
generally most vendors' LUTs are glitch-safe, ie. if the two LUT bits are actually the same, they'll reliably pick the value
<mei[m]>
weh i just want to stick the middle fine
<mei[m]>
s/fine/finger up verilog's butt/
<Wanda[cis]>
(oh, by the way, this is where X actually can come into play in FPGAs: not undefined primary inputs, but internal wires in the process of switching)
<Wanda[cis]>
mei[m]: kinky
<mei[m]>
oh, come on, butt stuff is kinky? what are you, a cishet?
<Wanda[cis]>
I'm fine with butt stuff, but Verilog?
<galibert[m]>
verilog stuff is kinky
<galibert[m]>
and we don't talk about vhdl
<Wanda[cis]>
what's better than 4-valued booleans? 9-valued booleans.
<galibert[m]>
isn't there one with 64-values booleans?
<Wanda[cis]>
eh someone probably made something
<Wanda[cis]>
it's not like Verilog has only 4 if you look closely
<Wanda[cis]>
have you seen the drive strength stuff?
<galibert[m]>
isn't that where there are the 64 levels indeed?
<Wanda[cis]>
mmm
<Wanda[cis]>
I haven't counted
<Wanda[cis]>
vaguely feels like more than that?
<galibert[m]>
maybe
<galibert[m]>
-EWAYTOOMANY
<Wanda[cis]>
anyway.
<Wanda[cis]>
if you want the evil twin of the current unnamed IR
<Wanda[cis]>
ControlNet is basically just Net + optional inverter
<Wanda[cis]>
it's called ControlNet because it's mostly used for control signals which tend to be used with various polarities
<Wanda[cis]>
(eg. ASICs love their active-low async resets)
<Wanda[cis]>
FPGAs just tend to have free bitstream-controlled inverters on control inputs (clocks pretty much always, resets and enables often), so we have the inversion as part of the cell where it can be extracted while techmapping
<galibert[m]>
cyclone v has optional inverters pretty much everywhere
<mei[m]>
so, are there any optimizations that introduce more X's?
<Wanda[cis]>
trick question
<Wanda[cis]>
I'm not sure how to interpret it
<Wanda[cis]>
increasing amount of X in netlist by volume? yeah sure that's going to happen in ways that are not related to X
<Wanda[cis]>
just because something gets mirrored somewhere
<Wanda[cis]>
generating an X where there was none before? that'd mostly be an invalid optimization unless you can prove the result isn't used
<Wanda[cis]>
there's the semi-const-folding rules that'll eg. replace the entire output of a mul with X if there's an X input bit at any position
<mei[m]>
wait, is that valid? what decides whether that's valid
<mei[m]>
you should be able to do truncations like with adds
<Wanda[cis]>
yes. which is why I'm thinking of changing this particular rule.
<Wanda[cis]>
the validity of the transformation is, of course, decided by the abstract model of what a mul cell is
<Wanda[cis]>
which we get to define however we want, to enable whatever optimization passes we want, as long as we stay within the constraints defined by the input and output languages
<Wanda[cis]>
the Verilog model of the * operator matches our current mul cell definition, which allows us to consume the Verilog operator directly into mul, and emit mul as * on Verilog output
<Wanda[cis]>
however, it doesn't allow the optimization
<Wanda[cis]>
we could change the model to be what you're implicitly proposing here, with X poisoning only higher bits
<Wanda[cis]>
then we'd still be able to ingest * operator directly, we'd now be able to perform the optimization, but we'd no longer be allowed to emit mul as * in Verilog
<Wanda[cis]>
annoying, isn't it
<leocassarani[m]>
So would you need to emit * as some kind of X-guard in front of a mul cell?
<Wanda[cis]>
hm?
<Wanda[cis]>
you mean in Verilog frontend?
<leocassarani[m]>
Is the issue that you'd need special handling for X values?
<leocassarani[m]>
Yes, sorry, in the Verilog to IR translation layer
<Wanda[cis]>
no, that's easy
<Wanda[cis]>
you can just import the cell directly in both cases
<Wanda[cis]>
you'll be relaxing the X behavior in the second case,but that's allowed; a synthesizer can always arbitrarily decide to replace an X with whatever
<leocassarani[m]>
Ooooh, of course
<Wanda[cis]>
IR to Verilog is where it gets tricky
<leocassarani[m]>
That's handy
<leocassarani[m]>
Yeah I can see what you're saying now
<Wanda[cis]>
oh, and by the way, for another major annoyance caused by X semantics, see Verilog LUT models
<Wanda[cis]>
it's one of these cases where the alternative would be pretty messy as well
<Wanda[cis]>
the alternative is "take every possible combination of X bits substituted with 0 and 1, check if all input bits at the index set are the same`
<Wanda[cis]>
* the alternative is "take every possible combination of X bits substituted with 0 and 1, check if all input bits at the index set are the same"