<jock-tanner>
Error (15065): Clock input port inclk[0] of PLL "pll:pll|altpll:pll|altpll_r601:auto_generated|pll1" must be driven by a non-inverted input pin or another PLL, optionally through a Clock Control block File: /home/tanner/workspace/pr092-nimgen_yosys/asceticore/build/db/altpll_r601.tdf Line: 27
<jock-tanner>
Info (15024): Input port INCLK[0] of node "pll:pll|altpll:pll|altpll_r601:auto_generated|pll1" is driven by pin_clk50_0_clk50_0__i which is COMBOUT output port of Combinational cell type node pin_clk50_0_clk50_0__i File: /home/tanner/workspace/pr092-nimgen_yosys/asceticore/build/db/altpll_r601.tdf Line: 27
<jock-tanner>
i don't understand why clk_50 becomes pin_clk50_0_clk50_0__i and if it's what i need
<jock-tanner>
maybe my problem is typical?
<agg>
jock-tanner: when you platform.request("clock_pin"), add dir="-"
<jock-tanner>
thank you agg, my pll is working now
<jock-tanner>
yay!
<agg>
Nice :)
<agg>
By default nmigen instantiates pin resources so you get the .i and can do things like input registers and ddr and so on and so forth, but for plls and other special cases you need just the raw pin directly which is what dir "-" does
<jock-tanner>
it is a bit strange, because i could not find anything similar in platform code
<jock-tanner>
i tried to mimmic Platform.create_missing_domain()
<lkcl__>
jock-tanner: allo :)
<jock-tanner>
pong lkcl =)
<lkcl__>
got an altera fpga, eh? (ooo, posh :) )
<jock-tanner>
it's de0-nano, i bought it very cheap on aliexpress
<lkcl__>
some advice: the more modules you use with wildcard imports, the harder it is to debug, particularly when asking someone else for help.
<FL4SHK>
there are no line numbers to help me this time
<lkcl__>
which module has DE0CVPlatform for example?
<FL4SHK>
nmigen-boards
<lkcl__>
ah, see i expected it to be in misc_util, or top_mod, or fifo_mod.
<FL4SHK>
nmigen_boards.de0_cv
<FL4SHK>
is where it's located
<lkcl__>
if at like 12 that had been "from nmigen_boards.de0_cv import DE0CVPlatform" i would not have had to ask :)
<lkcl__>
ok, so where is the ClockDomain declared?
<lkcl__>
it's not in main.py
<FL4SHK>
misc_util.py, add_clk_domain
<lkcl__>
alriiight :)
<lkcl__>
ok and where is inst_pll called from?
<FL4SHK>
top_mod.py
<FL4SHK>
in elaborate
<lkcl__>
i am wondering whether it's because the new domain has been added to a submodule
<FL4SHK>
I intended on the submodule being able to just use the clock signal created by the PLL
<lkcl__>
can i suggest adding a unit test that simply tries to instantiate Top() on its own?
<lkcl__>
oh, you already do - in main.py
<lkcl__>
line 46
<FL4SHK>
yes
<FL4SHK>
the problem seems to be in VgaDriver
<lkcl__>
possibly because VgaDriver hasn't had ClockDomain("dom") added to it?
<lkcl__>
can i make a suggestion?
<lkcl__>
modify nmigen/hdl/ir.py
<lkcl__>
line 117
<lkcl__>
to instead of saying this:
<lkcl__>
assert domain.name not in self.domains
<lkcl__>
say this:
<miek>
this looks like it's throwing an error on a duplicate domain, not a missing one
<lkcl__>
assert domain.name not in self.domains, "domain %s not in module %s" % (domain.name, str(self.domains))
<lkcl__>
assert "not in" means it's missing
<lkcl__>
or, better
<lkcl__>
assert domain.name not in self.domains, "domain %s not in module %s domains %s" % (domain.name, str(self), str(self.domains))
<lkcl__>
that will tell you:
<miek>
yeah, add_domains is asserting that it doesn't already exist
<lkcl__>
* the domain that's trying to be created
<lkcl__>
* the name of the module that the clock tree is attempting to build
<lkcl__>
* the list of domains already in that module
<lkcl__>
right now you are guessing.
<lkcl__>
FL4SHK: in case that wasn't clear, i'm recommending modifying the *NMIGEN* source code to give you better debug information
<FL4SHK>
yeah, that was clear
<FL4SHK>
I did it
<lkcl__>
it doesn't have to be a permanent modification, just enough to tell you what's going on
<FL4SHK>
AssertionError: domain dom not in module <nmigen.hdl.ir.Fragment object at 0x7f5317253d60> domains OrderedDict([('dom', <nmigen.hdl.cd.ClockDomain object at 0x7f531728bcd0>)])
<lkcl__>
bleh. not totally useful, yet :)
<lkcl__>
you see where i'm going with that? trying to look for the actual module (not the AST) that the code thinks "dom" is missing from
<lkcl__>
then when you know that module (it might be Top, it might be VGA) but we have no idea
<lkcl__>
once you know, it's possible to narrow down investigation
<miek>
..it's not missing
<lkcl__>
that assert says otherwise.
<lkcl__>
assert domain.name not in self.domains
<FL4SHK>
so I think I see something
<lkcl__>
that will only assert if the domain.name ("dom") in this case is missing from self.domains
<FL4SHK>
when do submodules get elaborated?
<FL4SHK>
do they get elaborated before the higher level one, or after it?
<lkcl__>
it's... complicated. they do *not* get elaborated in the constructor, that's for sure
<miek>
no, it will assert if "domain.name not in self.domains" evaluates to False - ie: it will assert if it already exists
<lkcl__>
i believe they are done leaf-nodes first
<FL4SHK>
yeah, asserts do work that way
<lkcl__>
miek, FL4SHK: yep, sorry :)
<FL4SHK>
VgaDriver's elaborate() should be adding a new clock domain to its module
<FL4SHK>
it calls `add_clk_domains`
<FL4SHK>
but actually
<FL4SHK>
even if I comment that out
<FL4SHK>
it won't work...
<FL4SHK>
same error message
<lkcl__>
hmmm what happens if you comment out line 92?
<lkcl__>
vga.drbus.clk.eq(ClockSignal("dom")) ?
<lkcl__>
i wonder if that's trying to create a *second* ClockDomain with the same name "dom" for you?
<FL4SHK>
same bug
<FL4SHK>
wait
<FL4SHK>
wait a minute
<FL4SHK>
removing the add_clk_domains thing works
<FL4SHK>
I had a separate clock signal within the VGA driver bus
<FL4SHK>
now I'm thinking that might not be necessary?
<lkcl__>
well... have a look at examples/board/02_domain.py
<lkcl__>
it might be the case that you need to do the domains at the top level?
<FL4SHK>
the bottom line is that I'm trying to have the generated clock signal from a PLL be attached to the domains of a submodule
<FL4SHK>
yes
<FL4SHK>
that's what I was thinking
<lkcl__>
ice cream van arrived, gotta go :)
<FL4SHK>
turns out that didn't work
<d1b2>
<286Tech> Ok, so apparently I misunderstood how to access the individual pins of a resource. I thought that I could do something like this: Resource("bla", 0, Pins("1 2 3 4", dir="oe",....) def elaborate(self, platform: Platform) -> Module: m = module() bla = platform.request("bla") for i in range(bla): m.d.comb += bla[i].oe.eq(...) m.d.comb += bla[i].o.eq(...)
<FL4SHK>
whitequark: so I want to use a PLL's generated clock with a submodule
<d1b2>
<286Tech> Because this gives the error "AttributeError: 'Slice' object has no attribute 'oe'"
<d1b2>
<286Tech> Ok, so the default value of the pin number is zero. That means that I'm not getting all pins, but just pin with index 0.
<d1b2>
<286Tech> How can I ask for the number of pins of a Resource? Because I cannot request it twice.
<d1b2>
<286Tech> I see that I can just do this: leds = [] for led in platform.request("led"): leds.append(led) This will store all the signals of "led" in a slice. Then I can do: for led in self.leds: m.d.comb += led.value.fields["oe"].eq(...) m.d.comb += led.value.fields["o"].eq(...)
<d1b2>
<286Tech> Seems a bit verbose, but I cannot access the oe and o signals directly (unless I'm doing something wrong, which is highly likely :D).
<agg>
You can just do led.o.eq(...)
<agg>
Yea sounds like something is going very wrong...
<d1b2>
<286Tech> I tried that, but then I get an error: AttributeError: 'Slice' object has no attribute 'o'
jeanthom has quit [Ping timeout: 256 seconds]
<agg>
Oh I see what you've done
<agg>
Iterating the single led signal gives you lots of individual bit slices not new signals
<agg>
normally you'd just do "led = platform.request("led")" and then `led` is a n-bit wide signal where each bit is an led, and it only has one oe (though why does your led line have oe at all?)
<FL4SHK>
whitequark: seems I only need to add a domain once
<FL4SHK>
this is good
<agg>
then you just m.d.comb += led.eq(0b1111) or led[0].eq(1) or led[5].eq(1) etc
<agg>
FL4SHK: i have an example making a pll and using it to clock a submodule etc, did you get yours working?
<d1b2>
<286Tech> agg: That's exactly what I have been trying to do, but that also didn't work (which means I did something wrong).
<FL4SHK>
agg: just now, yes!
<d1b2>
<286Tech> Let me try it again
<FL4SHK>
all I had to do was just use the existing domain
<agg>
ah yes indeed
<FL4SHK>
I didn't have to add it to the module
<agg>
domain names are global
<FL4SHK>
that's what I was missing
<agg>
you probably want to use DomainRenamer
<FL4SHK>
DomainRenamer?
<agg>
i usually would make all my modules use sync and then when you instantiate them in a top-level module you can rename that
<agg>
so e.g. you might have a VGADriver Elaboratable which has some synchronous logic
<agg>
use m.d.sync inside it for that
<agg>
but in your top level, when you'd do vga = VGADriver(); m.submodules += vga;
<agg>
instead do m.submodules += DomainRenamer("vga")(vga)
<agg>
which will rename sync into vga for that vga module and everything below it
<agg>
(you can also DomainRenamer({"sync": "vga"}) to be more explicit and rename other domains
<FL4SHK>
agg: so what about explicit reset signals? Are those still a thing?
<agg>
the domain includes a clk and an optional rst, so when you rename sync to vga it would also rename uses of resets to vga resets
<agg>
286Tech: I don't quite understand what you're trying to do with oe
<agg>
when you have a resource like that with multiple pins, it only gets one oe signal for the whole group
<agg>
so you want "self.leds.oe.eq(bla)" and "self.leds[5].eq(bla)" (or just self.leds.eq(bla))
<d1b2>
<286Tech> Ah of course! @whitequark even said it yesterday! doh!
<d1b2>
<286Tech> But shouldn't the o signal be individually addressable?
<agg>
oh, indeed, leds.o[5].eq(bla)
<agg>
it's a bit confusing that leds[5] works to be honest
<agg>
you probably also want len(leds.o)
<d1b2>
<286Tech> I get the same error for o too :/
<agg>
which error?
<d1b2>
<286Tech> AttributeError: 'Slice' object has no attribute 'o'
<d1b2>
<286Tech> Oh oops
<d1b2>
<286Tech> # LEDs m.d.comb += self.leds.oe.eq(~self.state_counter[0]) for i in range(len(self.leds)): m.d.comb += self.leds.o[i].eq(self.state_counter[1]) This gives me the error: IndexError: Cannot index 8 bits into 8-bit value
<d1b2>
<286Tech> I'm blind. You said len(leds.o), and that works.
<d1b2>
<286Tech> So len(self.leds) is wrong because it returns 1?
<agg>
no it actually returns 9
<agg>
self.leds has the oe signal and the 8-bit o signal
<agg>
so self.leds[0], [1], [2], etc indexes the o bits and the oe bit (can't remember in which order, probably oe last?)
<d1b2>
<286Tech> Ah ok. So they all get aggregated into a single slice/array/whatever-python-uses.
<d1b2>
<286Tech> That makes sense.
<d1b2>
<286Tech> I really need to write this down, because I'm going to forget and ask it again in the future 😛
<agg>
for plain inputs or plain outputs that means the different isn't obvious, leds.o is the same as leds
<d1b2>
<286Tech> Thanks for the help!
<agg>
but for oe and io it matters a lot more
<d1b2>
<286Tech> I see
<agg>
i think wq was talking about removing the ability to just do leds[5] because of this confusion
<agg>
it seems like it works with o and i, and then it's confusing when you move to io or oe
<d1b2>
<286Tech> I haven't use oe signals before, so that's why I never ran into this problem.
<agg>
basically for a resource you've got from a platform, you should always use the .o and .i signals
<agg>
there's also like .i_clk and .o_clk for sdr/ddr resources
<d1b2>
<286Tech> Being explicit in which signals you use avoids confusions like this.
jeanthom has joined #nmigen
<FL4SHK>
agg: can you go over a little of the reasons behind using DomainRenamer?
<FL4SHK>
how do I, for example, change which clock signal is in use by a submodule's `sync` domain?
<agg>
i picked a terrible day to try a totally new keyboard layout, lol
<agg>
so: i try to write my single-domain modules (i.e. domains that do not themselves contain cdc) to always use sync
<agg>
that way i can reuse them anywhere without worrying about domain names
<FL4SHK>
That's what I was looking at doing
<agg>
when they get instantiated, if they need to be in a domain other than sync, i use DomainRenamer to make any of their access to sync into whatever it is i want
<agg>
DomainRenamer(x) returns a function that takes an elaboratable and returns a new one with the domain renamed
<d1b2>
<Benny> > @Benny you were asking why anyone would use nmigen instead of VHDL or Verilog. > I think there is a pretty long list of reasons, and arguments one could make. I think the main goal of nmigen is to make designing complex digital hardware easier and faster. Also make sharing of designs and generation automation easier. So it is not just a novelty thing if you ask me, otherwise one could ask the same question of programming languages and we would still be
<d1b2>
writing Cobol 😄 (and yes, if we continue to discuss the merits here, let's try to keep this technical) @esden You did understand the question right ! And like I said I don't want to start a war but I can imagen it is easy for a python dev to quickly develop a design but besides that i can't imagen who would use it
<whitequark>
Benny: probably the single most important principle i use when developing nmigen is systematically eliminating programming errors
<whitequark>
with verilog, you have a lot of well-known footguns, and during your first few years of verilog programming, you're supposed to learn and adopt a "coding style" that makes them less likely
<whitequark>
what i say is that's bullshit. a good language would not have those footguns in first place
<lkcl__>
jock-tanner: if you use sv2nmigen on the opencores sdram controller code you'll get a long way much quicker
<lkcl__>
whitequark: yes, i was "trying to help" whilst you weren't available, by guiding him through a debug / investigative process. and learning as well.
<d1b2>
<Benny> " systematically eliminating programming errors" I'm not sure what you mean with that :/
<whitequark>
lkcl__: the problem with your attempts to help is that you spend more time editorializing your own opinions on things you don't understand than helping, and i do not appreciate that
<lkcl__>
whitequark: that's very strongly (alarmingly) worded, however i hear you: what did you have issue with?
<whitequark>
no, you don't hear me, this is the third time we have this discussion
<lkcl__>
was it the use of wildcards?
<lkcl__>
if it was the use of wildcards, that genuinely interfered with my ability to assist him.
<whitequark>
Benny: so for example, if you're using verilog, you have to be really careful to use only synthesizable constructs, and to avoid accidentally defining a latch
<d1b2>
<Benny> aaah ok, and that is not posible in nMigen?
<whitequark>
Benny: nmigen doesn't have non-synthesizable constructs, or constructs that map to a latch, at all
<whitequark>
yep
<lkcl__>
i genuinely could not tell which class was imported from which file, whether it was from a library, or code that he'd written, or code that someone else had written.
jeanthom has joined #nmigen
<d1b2>
<Benny> ok got it @whitequark and is there an industry that uses nMigen? because the industry standard is still verilog or vhdl or do i misunderstand that ?
<lkcl__>
this is simply one of the harmful side-effects of the use of wildcard imports: that only the author of the code or people who have memorised the contents of all libraries used by someone else's code can actually navigate it
<lkcl__>
what is wrong with saying that or explaining that?
<lkcl__>
i don't understand
<lkcl__>
if we're not communicating effectively, it's down to us to be patient with each other.
<whitequark>
this explanation is a lot better than what you said earlier, and i have no problem with it
<lkcl__>
Benny: Bluespec (BSV) which is written in Haskell goes to a lot of trouble to ensure that the output - which is verilog - is synthesiseable.
<FL4SHK>
whitequark: so, having requested the sd_card_spi from the platform, I get a weird error
<FL4SHK>
from synthesis
<whitequark>
Benny: nmigen is pretty young, so I wouldn't say there is an "industry" using it. however, it can output Verilog code, and you can use nMigen code in an existing Verilog flow
<lkcl__>
whitequark: i apologise, i have a delay in being able to explain things. i know something's "wrong" but it can take days even months to explain. this can be very frustrating, both for me and for others. please do be patient with me, i will get there
<whitequark>
hmm, the most interesting side effect of working on cxxsim is that i might be able to make pysim even faster
<whitequark>
i now see that the current pysim code is kind of pretty bad
<whitequark>
i'm not sure what i was thinking when i wrote it
<d1b2>
<mubes> If you're doing anything approximating to learning as you're working then any code older than 12 months is likely to look like a road crash....nothing to be ashamed about (hopefully some very old Pascal is so deeply buried by now even archiologists won't find it).
<whitequark>
yeah
<whitequark>
the two main things I see is SoA/AoS and explicit wakeup tracking vs comparing the full state
<whitequark>
there's also some really silly indirection going on
<lkcl__>
jock-tanner: sv2nmigen is a work-in-progress. has a budget available for anyone who wants to add to it.
jeanthom has quit [Ping timeout: 246 seconds]
<FL4SHK>
so I've got VGA signal generation working
<FL4SHK>
currently moving on to having the VGA driver read from a FIFO
<FL4SHK>
the VGA driver itself seems to be done
<FL4SHK>
I think I want to make a 2D, tile-based GPU
<jock-tanner>
lkcl__ that makes it more interesting =) it should support verilog, am iright?
jock-tanner has quit [Remote host closed the connection]
jock-tanner has joined #nmigen
<lkcl__>
jock-tanner: verilog == sv (kinda)
<lkcl__>
sv2nmigen was written to be able to translate parts of ariane into nmigen
<lkcl__>
unfortunately, the ariane team used a proprietary dialect of sv
<lkcl__>
so *sigh* i had to enhance the parser, which initially came from verilator
<jock-tanner>
lkcl__ seems like i have an error to report
<lkcl__>
jock-tanner: probably :) bugs.libre-soc.org is the best place.
<whitequark>
I asked daveshah to fix this because it would have prevented something like YoWASP from working
<whitequark>
(it doesn't include Python and really shouldn't)
<cr1901_modern>
Ahh cool, just making sure I'm not losing my grip on reality :)
<cr1901_modern>
It also helps me out immensely on my current work, since Boost.Python bindings are just plain annoying to change (although they are cool and seem to "just work" in general)
Asuu has joined #nmigen
Asu has quit [Ping timeout: 246 seconds]
Asuu has quit [Quit: Konversation terminated!]
<FL4SHK>
I have decided to move on to my main project in nMigen
<whitequark>
this part of nmigen-boards is kind of awkward
<whitequark>
but i think it's not too bad to use
<d1b2>
<ld;cd> yeah, its going alright though, mostly just building off the versa and changing all the pins
jeanthom has joined #nmigen
<d1b2>
<ld;cd> am I correct in asserting that there is currently no qspi resource type definied, or did I miss it somewhere
<d1b2>
<ld;cd> oh wait
<whitequark>
SPIFlashResources does support qspi
<d1b2>
<ld;cd> there is an io_4x thing in the normal spi flash
<d1b2>
<ld;cd> yeah
<d1b2>
<ld;cd> so I pass it through attrs
<d1b2>
<ld;cd> if the user requests the SPI interface when I've also defined the QSPI one will it work automagically or should I define a seperate qspi interface?
<whitequark>
I'm not sure what you mean by this
<whitequark>
you can request one interface at a time, because they all share pins
<d1b2>
<ld;cd> like is there a way to define one spi interface in the board file and the user can somehow decide whether they want to platform.request one version or the other, or should I define two seperate interfaces in the board file that they can request?
<whitequark>
SPIFlashResources already defines all interfaces
<whitequark>
all three: SPI, 2x, and 4x
<whitequark>
you request spi_flash_1x, spi_flash_2x, or spi_flash_4x depending on what you want
<d1b2>
<ld;cd> ok, cool
<FL4SHK>
anyone know how to get the fmax when using nmigen boards?
<FL4SHK>
I *could* just build a Quartus project, but...
<awygle>
you mean the final fmax after pnr?
<FL4SHK>
yeah
<awygle>
idk about the quartus flow (Lofty?) but in nextpnr it shows up in the output of the call to platform.build
<awygle>
By which I mean it gets printed to stdout
<tpw_rules>
it gets left in a file too. top.tim?
<FL4SHK>
there are soooo many things printed to stdout
<tpw_rules>
my nmigen builds never print anything to stdout
<FL4SHK>
I don't see `top.tim` anywhere
<tpw_rules>
maybe it's because i use a bastardized version of nmigen cli