| --- Sat Jul 21 2012 | 00:00 | |
| Fallenou | hum I wonder what happens when an exception happens (exception_x == TRUE) but stall_m or stall_x are TRUE, or q_x == FALSE | 14:45 |
|---|---|---|
| Fallenou | Do we lose the exception ? | 14:45 |
| Fallenou | see lm32_cpu.v there : https://github.com/milkymist/milkymist/blob/master/cores/lm32/rtl/lm32_cpu.v#L2579 | 14:46 |
| Fallenou | We sould not lose the exception, in any case, 'cause exception origin could be an interrupt for example | 14:47 |
| Fallenou | and interrupt can happen any time, without any concern on pipeline state (stalls, kills, etc) | 14:47 |
| Fallenou | I don't understand why exception_x does not et propagated all the time to exception_m | 14:47 |
| Fallenou | does not get* | 14:47 |
| Fallenou | or maybe the exception_x signal *MUST* be kept high untill it gets propagated to exception_m ? | 14:49 |
| Fallenou | that's what I am doing for now | 14:49 |
| Fallenou | I keep i/d tlb miss flag asserted untill I see exception_m asserted | 14:49 |
| Fallenou | but I find this strange | 14:50 |
| 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 | 14:50 |
| Fallenou | in lm32_top.v interrupt pins are passed to lm32_cpu (pipeline) as a wire | 14:51 |
| Fallenou | and then in lm32_interrupt.v there is a assign asserted = interrupt_pins & ie | 14:52 |
| Fallenou | and then the exception_x gets assigned to (asserted & im) something like that | 14:53 |
| 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 | 14:54 |
| Fallenou | wpwrak: interrupts are level triggered | 14:54 |
| Fallenou | but the level has to be kept for a few clock cycles sometimes | 14:55 |
| Fallenou | you have to wait exception_m becomes `TRUE, to be *sure* that the exception will happen later on | 14:55 |
| Fallenou | so you need to keep exception_x asserted, untill all condition for propagation from exception_x to exception_m are met | 14:56 |
| Fallenou | like stall_m = false, stall_x=false, q_x = true | 14:56 |
| wpwrak | the general rule for level-triggered interrupts is that they have to be asserted until there is a reaction | 15:17 |
| wpwrak | so that logic seems fine | 15:17 |
| Fallenou | ok | 15:20 |
| lekernel | interrupt inputs are edge triggered on the original LM32 | 16:06 |
| lekernel | a pulse sets the corresponding bit in IP at any time (regardless of the pipeline state) | 16:06 |
| lekernel | and that bit stays set until IP is written (w1c) | 16:06 |
| lekernel | the pipeline sees only a "level" type of signal that is asserted whenever at least one bit is asserted in IP | 16:07 |
| 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.) | 16:08 |
| Fallenou | ok | 16:10 |
| Fallenou | in milkymist master branch it's level sensitif, right ? | 16:11 |
| Fallenou | you modified the original lm32 | 16:11 |
| lekernel | if you're using lm32 from milkymist-ng, it's level sensitive, yes | 16:13 |
| lekernel | internally they're always level-sensitive anyway | 16:13 |
| Fallenou | oh ok now i can see, asserted gets stored into ip | 16:17 |
| Fallenou | ok got it thx | 16:17 |
| Fallenou | itlb is really starting to work nicely on fpga | 22:31 |
| Fallenou | it's really less buggy than it was a week ago now | 22:32 |
| Fallenou | still something weird in ITLB miss handler | 22:34 |
| Fallenou | let me pastebin it :) | 22:35 |
| wpwrak | what was the big problem ? | 22:40 |
| Fallenou | http://pastebin.com/zMsxxh3M | 22:42 |
| Fallenou | wpwrak: I was mostly putting delays in value propagations from reg to reg in clock cycles | 22:43 |
| Fallenou | instead of doing it in "pipeline cycles" | 22:43 |
| Fallenou | so in simulation it was "correct" because the two were correctly synchronized because I was able to see wire values etc | 22:43 |
| Fallenou | but on fpga there is a lot of difference, because there is a real DDR SDRAM controler on the wishbone bus etc | 22:43 |
| Fallenou | so I was doing it totally wrong :) | 22:44 |
| Fallenou | now I look for stalls in the pipeline for instance | 22:44 |
| Fallenou | and strangely, it works really better now ! | 22:44 |
| Fallenou | I can : enable itlb and jump to a function with it's virtual address | 22:45 |
| Fallenou | I can run (with itlb enabled) a function calling puts() and printf(), with ITLB totally flushed | 22:45 |
| Fallenou | which means it's going to generate a whole bunch of tlb miss (exceptions) , ITLB update and go back to code etc | 22:46 |
| Fallenou | and it works | 22:46 |
| Fallenou | "it works", but there is the bug I just posted in pastebin | 22:46 |
| Fallenou | :) | 22:46 |
| wpwrak | hmm. what does "delay" mean in this case ? i suppose isn't not something like "wait 100 ns here", is it ? | 22:46 |
| Fallenou | no it's like cascading flip flops | 22:47 |
| 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 | 22:48 |
| wpwrak | so you propagate between clock cycles ? i.e., from one "run" of an always block to its next "run" ? | 22:48 |
| Fallenou | yes, I was doing things like that | 22:49 |
| Fallenou | it kind of worked, but it was really stupid | 22:49 |
| wpwrak | ah, perfect :) and i suppose these delays are constant, i.e., don't depend on, say, bus activity ? | 22:49 |
| 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 | 22:50 |
| Fallenou | you cannot assume that pipeline will go forward at each clock cycle | 22:50 |
| Fallenou | and I was assuming that | 22:50 |
| wpwrak | ah, i see. so now you basically have a parallel pipeline | 22:51 |
| Fallenou | but now I am turning crazy, because if I remove a rcsr it goes in an infinite exception loop :) | 22:51 |
| wpwrak | and i can see how getting the delays wrong could cause very interesting bugs ;-)) | 22:51 |
| Fallenou | wpwrak: well not sure if I understand what you means, but now we can say that I am doing it correctly :) | 22:51 |
| Fallenou | yes ^^ | 22:51 |
| Fallenou | wpwrak: my problem now is that somehow EA (exception address, where you branch upon eret) gets the value of itlb_miss_handler | 22:52 |
| Fallenou | I don't get how, but it happens | 22:52 |
| wpwrak | ;-)) | 22:53 |
| Fallenou | so when you eret, you branch to itlb_miss_handler, and then you eret etc etc | 22:53 |
| Fallenou | and I just added a rcsr to read the value of PSW | 22:53 |
| Fallenou | and it "fixed" the whole thing | 22:53 |
| Fallenou | and btw PSW is correct, it's value is 0x10 | 22:53 |
| wpwrak | maybe you're coying the PC a little too late ? | 22:53 |
| Fallenou | which means EITLBE = 1 and ITLBE = 0 | 22:53 |
| Fallenou | EITLBE = Exception ITLB enable | ITLBE = ITLB enabled | 22:54 |
| Fallenou | upon exception ITLBE is copied to EITLBE and ITLBE is cleared | 22:54 |
| Fallenou | so it seems correct | 22:54 |
| Fallenou | too late or too early | 22:55 |
| Fallenou | too early maybe | 22:55 |
| wpwrak | sounds as if you're copying PC -> EA too late. i.e., after the exception has already been started. | 22:56 |
| Fallenou | look at the logs, EA is correct two times | 22:56 |
| Fallenou | for the first two ITLB misses | 22:56 |
| Fallenou | and then it gets ***120 (which is itlb_miss_handler address) | 22:57 |
| Fallenou | well you may be right, "too late" | 22:57 |
| wpwrak | maybe it's concurrent ? | 22:58 |
| Fallenou | wpwrak: do you see why just commenting/uncommenting the rcsr somehow fixes or not the whole thing ? :o | 22:58 |
| Fallenou | I just don't get this | 22:58 |
| Fallenou | the instruction is in the middle of the tlb handler | 22:58 |
| wpwrak | maybe that's just coincidence. or maybe it affects cache timing or such. | 23:00 |
| Fallenou | I think I'm going to commit/push ITLB to github | 23:01 |
| Fallenou | now it's really less buggy | 23:01 |
| 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 ? | 23:02 |
| Fallenou | you cannot assign the value variable from two places running in // | 23:03 |
| Fallenou | it fails to "compile" in ISim and in Xst as well | 23:03 |
| wpwrak | ah, i see | 23:03 |
| wpwrak | pity. that takes the fun out of a lot of very interesting mistakes :) | 23:04 |
| Fallenou | if you have a reg that you assign with "<=", you can assign it ONLY from one always block | 23:04 |
| Fallenou | you can assign it in several if / else / switch case statements if you want | 23:04 |
| wpwrak | how about "=" ? | 23:05 |
| Fallenou | but you cannot have two different always blocks, assigning the same reg or wire | 23:05 |
| Fallenou | it's the same | 23:05 |
| Fallenou | to say it more efficiently : a signal can only be driven by one block | 23:05 |
| 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 | 23:06 |
| Fallenou | and I am doing a lot of them :D | 23:07 |
| Fallenou | let's track how the pipeline writes to EA upon exception :' | 23:10 |
| --- Sun Jul 22 2012 | 00:00 | |
Generated by irclog2html.py 2.9.2 by Marius Gedminas - find it at mg.pov.lt!