<d1b2>
<4o> why do i see errors only when i ask for help...:)
<d1b2>
<4o> why do i see errors only when i ask for help...:)
<d1b2>
<4o> yeah. cause i create an array of types, not the array of instances
<d1b2>
<4o> yeah. cause i create an array of types, not the array of instances
slan has joined #nmigen
slan has joined #nmigen
<slan>
Hmm... still trying to figure out how to make my interconnect work. I think I've hit a wall.
<slan>
Hmm... still trying to figure out how to make my interconnect work. I think I've hit a wall.
<slan>
Context: a cpu, 2 read ports. Goal: fetching and reading memory should happen in 1 cycle if read ports are different, 2 cycles otherwise.
<slan>
Context: a cpu, 2 read ports. Goal: fetching and reading memory should happen in 1 cycle if read ports are different, 2 cycles otherwise.
<slan>
My problem: simulation works fine, synthesis is reporting 10 combinatorial loops.
<slan>
My problem: simulation works fine, synthesis is reporting 10 combinatorial loops.
emeb has joined #nmigen
emeb has joined #nmigen
<slan>
At this point, I'm not sure if 1. this is doable 2. this is doable with nmigen 3. there is a bug in the nmigen -> yosys -> vivado chain 4. my implementation is broken
<slan>
At this point, I'm not sure if 1. this is doable 2. this is doable with nmigen 3. there is a bug in the nmigen -> yosys -> vivado chain 4. my implementation is broken
<slan>
Since I'm a beginner, I'm focusing on 4 but after rewriting and simplifying my design many times I'm getting similar results and I'm running out of ideas on how to investigate further.
<slan>
Since I'm a beginner, I'm focusing on 4 but after rewriting and simplifying my design many times I'm getting similar results and I'm running out of ideas on how to investigate further.
<slan>
daddr -> iport addr should be gated by the "collision" detection
<slan>
daddr -> iport addr should be gated by the "collision" detection
<agg>
yes, I see
<agg>
yes, I see
<agg>
you sure are making your life difficult :p
<agg>
you sure are making your life difficult :p
<agg>
the muxes i drew on the memory address inputs are wrong too, actually
<agg>
the muxes i drew on the memory address inputs are wrong too, actually
<slan>
The reasoning behind this "exercise" is that I would like my CPU to work with distributed RAM (as L1 cache) backed by BRAM/SDRAM
<slan>
The reasoning behind this "exercise" is that I would like my CPU to work with distributed RAM (as L1 cache) backed by BRAM/SDRAM
<slan>
So I'm aiming at 1 CPI if possible
<slan>
So I'm aiming at 1 CPI if possible
<slan>
And the reason I'm thinking of a bug in the nmigen -> yosys -> vivado chain is that if I change L57 with a constant value, everything works as expected
<slan>
And the reason I'm thinking of a bug in the nmigen -> yosys -> vivado chain is that if I change L57 with a constant value, everything works as expected
<slan>
but I'm losing the ability to run code from different memories
<slan>
but I'm losing the ability to run code from different memories
<agg>
I still expect there's a combinatorial feedback loop in here, and they're explicitly UB in nmigen
<agg>
I still expect there's a combinatorial feedback loop in here, and they're explicitly UB in nmigen
<agg>
but maybe not, in which case maybe there's a bug creeping in somewhere instead
<agg>
but maybe not, in which case maybe there's a bug creeping in somewhere instead
<slan>
Yes, that's the reason I'm also suspecting my implementation is broken: I think my idea should not create combinatorial loops. Maybe I failed to express my intention to nmigen
<slan>
Yes, that's the reason I'm also suspecting my implementation is broken: I think my idea should not create combinatorial loops. Maybe I failed to express my intention to nmigen
<slan>
but I've tried to approach the problem from as many angles as I could think of
<slan>
but I've tried to approach the problem from as many angles as I could think of
<slan>
without much success...
<slan>
without much success...
Bertl is now known as Bertl_oO
Bertl is now known as Bertl_oO
<agg>
slan: it might help clarify the design if you're more explicit about what drives each read port's addr signal
<agg>
slan: it might help clarify the design if you're more explicit about what drives each read port's addr signal
<agg>
which rp sources each data signal is very clear, but it's much less obvious what the control signal to the mux on the memory address is
<agg>
which rp sources each data signal is very clear, but it's much less obvious what the control signal to the mux on the memory address is
emeb_mac has joined #nmigen
emeb_mac has joined #nmigen
<agg>
just a vague thought though
<agg>
just a vague thought though
<slan>
Maybe I'll try. I'm not used to thinking in terms of mux/circuit since I have no formal education in this. Just played a bit with logisim... that could help calarify
<slan>
Maybe I'll try. I'm not used to thinking in terms of mux/circuit since I have no formal education in this. Just played a bit with logisim... that could help calarify
<slan>
good idea, thanks
<slan>
good idea, thanks
<slan>
(agree that the mux driving memory access is tricky)
<slan>
(agree that the mux driving memory access is tricky)
emeb_mac has quit [Quit: Leaving.]
emeb_mac has quit [Quit: Leaving.]
<agg>
slan: hm, thinking about the mem addr muxes, I think you have a problem where insn (and thus daddr) is fed combinatorially from the two read port datas, and both read port addresses combinatorially depend on daddr
<agg>
slan: hm, thinking about the mem addr muxes, I think you have a problem where insn (and thus daddr) is fed combinatorially from the two read port datas, and both read port addresses combinatorially depend on daddr
<agg>
even though it should be a _stable_ feedback loop because eventually your conditions are exclusive, it's still a combinatorial loop, I think
<agg>
even though it should be a _stable_ feedback loop because eventually your conditions are exclusive, it's still a combinatorial loop, I think
<agg>
rp0.addr depends on daddr which depends on insn which depends on rp0.data which depends on rp0.addr, basically, even though once it settles down it will find a stable value
<agg>
rp0.addr depends on daddr which depends on insn which depends on rp0.data which depends on rp0.addr, basically, even though once it settles down it will find a stable value
<slan>
How can insn be fed by the 2 read ports? Isn't it either from a readport or from the cache?
<slan>
How can insn be fed by the 2 read ports? Isn't it either from a readport or from the cache?
<agg>
it's from iport which might be rp0 or rp1 combinatorially
<agg>
it's from iport which might be rp0 or rp1 combinatorially
<agg>
only depending on pc and cache_addr, but the rp0/rp1.addr signal depends on both pc and daddr to select whether it's iport or dport
<agg>
only depending on pc and cache_addr, but the rp0/rp1.addr signal depends on both pc and daddr to select whether it's iport or dport
<slan>
I don't see it... let's take my example of booting from mem1, reading from rp0 gives: pc -> rp1.addr -> insn -> rp0.addr
<slan>
I don't see it... let's take my example of booting from mem1, reading from rp0 gives: pc -> rp1.addr -> insn -> rp0.addr
<slan>
reading from rp1 gives: pc -> rp1.addr -> insn -> cache / next cycle cache -> insn -> rp1.addr
<slan>
reading from rp1 gives: pc -> rp1.addr -> insn -> cache / next cycle cache -> insn -> rp1.addr
<slan>
assuming cache_addr cache_insn are registers there should be no dependency, right?
<slan>
assuming cache_addr cache_insn are registers there should be no dependency, right?
<agg>
if you look at it the other way, rp0.addr is fed from a combinatorial circuit with inputs pc, cache_addr, daddr, dreq
<agg>
if you look at it the other way, rp0.addr is fed from a combinatorial circuit with inputs pc, cache_addr, daddr, dreq
<agg>
so is rp1
<agg>
so is rp1
<agg>
and daddr is a wire that is generated from a combinatorial circuit fed by cache_insn and rp0.data and rp1.data
<agg>
and daddr is a wire that is generated from a combinatorial circuit fed by cache_insn and rp0.data and rp1.data
<agg>
so the logic generating the rp0.addr signal has the rp0.data signal as an input
<agg>
so the logic generating the rp0.addr signal has the rp0.data signal as an input
<slan>
I think I see. Although I agree it should be stable.
<slan>
I think I see. Although I agree it should be stable.
<agg>
unfortunately it being stable doesn't matter
<agg>
unfortunately it being stable doesn't matter
<agg>
in terms of nmigen, anyway
<agg>
in terms of nmigen, anyway
<slan>
Hmm... do you think I can turn that stable loop into something nmigne would be happy with?
<slan>
Hmm... do you think I can turn that stable loop into something nmigne would be happy with?
<slan>
Drawing more (not fully there yet) makes me feel I could have a priority encoder in fromt of the ports to decide if fetch or mem should have access
<slan>
Drawing more (not fully there yet) makes me feel I could have a priority encoder in fromt of the ports to decide if fetch or mem should have access
<slan>
In practice turning the problem upside down and starting (as you hinted) with the "mux" to mem
<slan>
In practice turning the problem upside down and starting (as you hinted) with the "mux" to mem
revolve has quit [Read error: Connection reset by peer]
revolve has quit [Read error: Connection reset by peer]
<slan>
AH but no... I need the fetch in any case... maybe I'll finish my drawing and look into instancing a lath (as per nmigen doc)
<slan>
AH but no... I need the fetch in any case... maybe I'll finish my drawing and look into instancing a lath (as per nmigen doc)
<slan>
^latch
<slan>
^latch
revolve has joined #nmigen
revolve has joined #nmigen
<slan>
I could also have the interconnect as a module with a 2x clock (and make all mem instructions execute in 2 cycles). I'm wondering, in general, how people go about harvard -> modified harvard architecture (which, I believe, is what I'm aiming for)
<slan>
I could also have the interconnect as a module with a 2x clock (and make all mem instructions execute in 2 cycles). I'm wondering, in general, how people go about harvard -> modified harvard architecture (which, I believe, is what I'm aiming for)
bvernoux has joined #nmigen
bvernoux has joined #nmigen
<agg>
slan: yea, it's tricky, I guess most "serious" designs are pipelined so it stops being a problem
<agg>
slan: yea, it's tricky, I guess most "serious" designs are pipelined so it stops being a problem
<agg>
if you can make the memory sync that certainly solves it
<agg>
if you can make the memory sync that certainly solves it
<slan>
How come pipeline solves it? You will have one fetch and 1 mem read per cycle anyways, no?
<slan>
How come pipeline solves it? You will have one fetch and 1 mem read per cycle anyways, no?
<agg>
i assume the pipeline means the memory becomes synchronous, so there's no longer a combinatorial feedback path through the memory at all
<agg>
i assume the pipeline means the memory becomes synchronous, so there's no longer a combinatorial feedback path through the memory at all
<agg>
and/or the address input comes from a register from the previous pipeline stage, again breaking the loop
<agg>
and/or the address input comes from a register from the previous pipeline stage, again breaking the loop
<agg>
you still get 1 cpi, but with a latency equal to the number of stages
<agg>
you still get 1 cpi, but with a latency equal to the number of stages
* agg
is not a cpu designer by any stretch of the imagination, now at the edge of what I know :p
* agg
is not a cpu designer by any stretch of the imagination, now at the edge of what I know :p