<Fallenou>
We sould not lose the exception, in any case, 'cause exception origin could be an interrupt for example
<Fallenou>
and interrupt can happen any time, without any concern on pipeline state (stalls, kills, etc)
<Fallenou>
I don't understand why exception_x does not et propagated all the time to exception_m
<Fallenou>
does not get*
<Fallenou>
or maybe the exception_x signal *MUST* be kept high untill it gets propagated to exception_m ?
<Fallenou>
that's what I am doing for now
<Fallenou>
I keep i/d tlb miss flag asserted untill I see exception_m asserted
<Fallenou>
but I find this strange
<wpwrak>
losing an exception would be bad indeed. are interrupts edge-triggered ? because if they're level-triggered, then an interrupt that's not handled will simply come back in the next cycle
<Fallenou>
in lm32_top.v interrupt pins are passed to lm32_cpu (pipeline) as a wire
<Fallenou>
and then in lm32_interrupt.v there is a assign asserted = interrupt_pins & ie
<Fallenou>
and then the exception_x gets assigned to (asserted & im) something like that
<Fallenou>
it's all wire stuff, without any reg, so if the interrupt pin is de asserted before exception is triggered, there is no exception
<Fallenou>
wpwrak: interrupts are level triggered
<Fallenou>
but the level has to be kept for a few clock cycles sometimes
<Fallenou>
you have to wait exception_m becomes `TRUE, to be *sure* that the exception will happen later on
<Fallenou>
so you need to keep exception_x asserted, untill all condition for propagation from exception_x to exception_m are met
<Fallenou>
like stall_m = false, stall_x=false, q_x = true
lekernel has quit [Read error: Operation timed out]
lekernel has joined #milkymist
lekernel_ has joined #milkymist
lekernel has quit [Ping timeout: 255 seconds]
<wpwrak>
the general rule for level-triggered interrupts is that they have to be asserted until there is a reaction
<wpwrak>
so that logic seems fine
<Fallenou>
ok
jaho has joined #milkymist
jaho has quit [Quit: Salut a tous]
lekernel_ is now known as lekernel
<lekernel>
interrupt inputs are edge triggered on the original LM32
<lekernel>
a pulse sets the corresponding bit in IP at any time (regardless of the pipeline state)
<lekernel>
and that bit stays set until IP is written (w1c)
<lekernel>
the pipeline sees only a "level" type of signal that is asserted whenever at least one bit is asserted in IP
<lekernel>
(in the LM32 used in -ng, I have removed this mechanism and made IP read-only, with its bit directly set by the now level-sensitive interrupt inputs. that should indeed be kept asserted by individual cores until there is a reaction from the CPU.)
<Fallenou>
ok
<Fallenou>
in milkymist master branch it's level sensitif, right ?
<Fallenou>
you modified the original lm32
<lekernel>
if you're using lm32 from milkymist-ng, it's level sensitive, yes
<Fallenou>
wpwrak: I was mostly putting delays in value propagations from reg to reg in clock cycles
<Fallenou>
instead of doing it in "pipeline cycles"
<Fallenou>
so in simulation it was "correct" because the two were correctly synchronized because I was able to see wire values etc
<Fallenou>
but on fpga there is a lot of difference, because there is a real DDR SDRAM controler on the wishbone bus etc
<Fallenou>
so I was doing it totally wrong :)
<Fallenou>
now I look for stalls in the pipeline for instance
<Fallenou>
and strangely, it works really better now !
<Fallenou>
I can : enable itlb and jump to a function with it's virtual address
<Fallenou>
I can run (with itlb enabled) a function calling puts() and printf(), with ITLB totally flushed
<Fallenou>
which means it's going to generate a whole bunch of tlb miss (exceptions) , ITLB update and go back to code etc
<Fallenou>
and it works
<Fallenou>
"it works", but there is the bug I just posted in pastebin
<Fallenou>
:)
<wpwrak>
hmm. what does "delay" mean in this case ? i suppose isn't not something like "wait 100 ns here", is it ?
<Fallenou>
no it's like cascading flip flops
<Fallenou>
I want to use the value of regX, but two clock cycles later, I do always @(posedge clk) regX1 <= regX and always @(posedge clk) regX2 <= regX1; and I use regX2
<wpwrak>
so you propagate between clock cycles ? i.e., from one "run" of an always block to its next "run" ?
<Fallenou>
yes, I was doing things like that
<Fallenou>
it kind of worked, but it was really stupid
<wpwrak>
ah, perfect :) and i suppose these delays are constant, i.e., don't depend on, say, bus activity ?
<Fallenou>
most of the time one clock cycle ~ 1 pipeline cycle but there are cases where you have stalls (upon branches, dcache refill, icache refill) and there you are screwed
<Fallenou>
you cannot assume that pipeline will go forward at each clock cycle
<Fallenou>
and I was assuming that
<wpwrak>
ah, i see. so now you basically have a parallel pipeline
<Fallenou>
but now I am turning crazy, because if I remove a rcsr it goes in an infinite exception loop :)
<wpwrak>
and i can see how getting the delays wrong could cause very interesting bugs ;-))
<Fallenou>
wpwrak: well not sure if I understand what you means, but now we can say that I am doing it correctly :)
<Fallenou>
yes ^^
<Fallenou>
wpwrak: my problem now is that somehow EA (exception address, where you branch upon eret) gets the value of itlb_miss_handler
<Fallenou>
I don't get how, but it happens
<wpwrak>
;-))
<Fallenou>
so when you eret, you branch to itlb_miss_handler, and then you eret etc etc
<Fallenou>
and I just added a rcsr to read the value of PSW
<Fallenou>
and it "fixed" the whole thing
<Fallenou>
and btw PSW is correct, it's value is 0x10
<wpwrak>
maybe you're coying the PC a little too late ?
<Fallenou>
upon exception ITLBE is copied to EITLBE and ITLBE is cleared
<Fallenou>
so it seems correct
<Fallenou>
too late or too early
<Fallenou>
too early maybe
<wpwrak>
sounds as if you're copying PC -> EA too late. i.e., after the exception has already been started.
<Fallenou>
look at the logs, EA is correct two times
<Fallenou>
for the first two ITLB misses
<Fallenou>
and then it gets ***120 (which is itlb_miss_handler address)
<Fallenou>
well you may be right, "too late"
<wpwrak>
maybe it's concurrent ?
<Fallenou>
wpwrak: do you see why just commenting/uncommenting the rcsr somehow fixes or not the whole thing ? :o
<Fallenou>
I just don't get this
<Fallenou>
the instruction is in the middle of the tlb handler
<wpwrak>
maybe that's just coincidence. or maybe it affects cache timing or such.
<Fallenou>
I think I'm going to commit/push ITLB to github
<Fallenou>
now it's really less buggy
<wpwrak>
if you have conflicting operations in the simulator, e.g., you assign to the same variable from two different places that could execute in parallel. what will the simulator do ? warn you ? pick always a given order ? pick an arbitrary but unspecified order ? or pick a randomize order ?
<Fallenou>
you cannot assign the value variable from two places running in //
<Fallenou>
it fails to "compile" in ISim and in Xst as well
<wpwrak>
ah, i see
<wpwrak>
pity. that takes the fun out of a lot of very interesting mistakes :)
<Fallenou>
if you have a reg that you assign with "<=", you can assign it ONLY from one always block
<Fallenou>
you can assign it in several if / else / switch case statements if you want
<wpwrak>
how about "=" ?
<Fallenou>
but you cannot have two different always blocks, assigning the same reg or wire
<Fallenou>
it's the same
<Fallenou>
to say it more efficiently : a signal can only be driven by one block
<Fallenou>
01:11 < wpwrak> pity. that takes the fun out of a lot of very interesting mistakes :) < there is already a lot of room for mistakes, trust me :p
<Fallenou>
and I am doing a lot of them :D
<Fallenou>
let's track how the pipeline writes to EA upon exception :'