Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HW, RV_PLIC] Claim/Complete register behaviour on FPGA #1355

Closed
silvestrst opened this issue Jan 16, 2020 · 26 comments
Closed

[HW, RV_PLIC] Claim/Complete register behaviour on FPGA #1355

silvestrst opened this issue Jan 16, 2020 · 26 comments
Labels
Component:FPGA FPGA related issues Type:Bug Bugs

Comments

@silvestrst
Copy link
Contributor

Interrupts are firing in verilator but not FPGA. This issue has been first discovered by @alistair23 working on Tock. I have also ran into this issue when doing some proof-of-concept work, related to #1330 .

After examining the netlist, it seems that portions of RV_PLIC are optimised by the FPGA synthesis tool (rv_plic_target, as well as cc0 in rv_plic_reg_top). One of the hypothesis is that parts of PLIC have been optimised out by the synthesis tool, possibly as result of @msfschaffner PLIC rework.

We have set up a set of relevant UART and PLIC signals in the Integrated Logic Analyser, and triggered an UART TX watermark interrupt. Thus, we would expect to read a value of 33 from CC0 (the interrupt claim register). However, we observed the following results:

  • The inputs to CC0 are always 0 (IP1 = 0x00000001, IE01 = 0x00000001, Priority = 0x00000003, THRESHOLD0 = 0x00000000, LE1 = 0x00000000, both settings for edge- and level-sensitivity did not make any difference)
  • The output of CC0 (complete_id) with ILA shows 1 after a read by the core, however the value the core receives is 0. The expected value would be 33 for the UART TX watermark interrupt.

Thank you @GregAC for setting up ILA, and @vogelpi for going through RTL with me.

@silvestrst
Copy link
Contributor Author

@msfschaffner @eunchan could you please look into this?

@GregAC
Copy link
Contributor

GregAC commented Jan 16, 2020

So from looking at the ILA outputs what's happening is the gateway seems to set the ip and ia flops up correctly (i.e. bit 32 gets set when the TX watermark interrupt is triggered) but something goes wrong in the target presumably in the logic that determines the highest priority. The reg2hw.cc0.q signal reads as 'h1 on the ILA (well I'm actually probing complete_id[0] but it's assigned to reg2hw.cc0.q) but SW cannot read this value for whatever reason.

Again from the ILA output I don't think the irq_q flop is getting set in the target module (perhaps this causes CC0 to get masked to 0 somewhere?)

@silvestrst
Copy link
Contributor Author

The SW proof-of-concept code that I have put together lives here

@asb asb added Component:FPGA FPGA related issues Type:Bug Bugs labels Jan 16, 2020
@eunchan
Copy link
Contributor

eunchan commented Jan 16, 2020

Thanks for reporting the issue. When @alistair23 reported this, I overlooked the chance of optimized away the logic. Let me and @msfschaffner dig this issue. Thanks!

CC: @tjaychen

@eunchan
Copy link
Contributor

eunchan commented Jan 16, 2020

CC: @phil-levis-google

@msfschaffner
Copy link
Contributor

msfschaffner commented Jan 16, 2020

Thanks for reporting this issue. Might be a simulation/synthesis mismatch, yes. The fastest way to test your hypothesis would be to build two bitstreams (one with the old and one with the new plic target). I've just kicked these builds off and will test them with the uart test.

@msfschaffner
Copy link
Contributor

msfschaffner commented Jan 17, 2020

Ok after running the uart test on both versions (i.e. old/new plic target) in simulation as well as on FPGA, I can confirm that we are likely seeing a simulation/synthesis mismatch here.

I could not root-cause the mismatch just yet (the synthesis reports do not offer any insight). Will continue digging tomorrow.

In the mean time you can use the hotfix
3828f60da05cacf54c9cac9352a6d4b66c6e49ea
which lives here:
https://github.com/msfschaffner/opentitan/tree/irq-proof-of-concept
I based this on top of @silvestrst branch, and it basically reverts the plic target to an older implementation.

Note that synthesis might take considerably longer since that implementation does not scale well to so many interrupt sources (63). Also, please do not yet merge this fix into the main repository if possible. I hope that we will find the actual bug soon such that we can use the new implementation.

@msfschaffner
Copy link
Contributor

Btwy, I am using Vivado v2018.3. Has anyone tried with a different version than that yet?

@silvestrst
Copy link
Contributor Author

@msfschaffner and @eunchan thank you for looking into this problem, and for the patch.

Btwy, I am using Vivado v2018.3. Has anyone tried with a different version than that yet?

I use the same version as you.

@silvestrst
Copy link
Contributor Author

@msfschaffner I have tried your temporary patch, and can confirm that I can get TX watermark interrupt to fire on the FPGA. Thank you

@GregAC
Copy link
Contributor

GregAC commented Jan 17, 2020

Tried with Vivado 2019.2, synthesis tool just crashes early, there's some messages from a memory allocater reporting large allocs. Looks like it runs out of memory and crashes.

However the reported allocs have a suspicious progress of sizes:

tcmalloc: large alloc 1073741824 bytes == 0x6d238000 @  0x7f3b8bff463f 0x7f3b494195ce
tcmalloc: large alloc 2147483648 bytes == 0xad238000 @  0x7f3b8bff463f 0x7f3b494195ce
tcmalloc: large alloc 4294967296 bytes == 0x12d238000 @  0x7f3b8bff463f 0x7f3b494195ce
tcmalloc: large alloc 8589934592 bytes == (nil) @  0x7f3b8bff463f 0x7f3b494195ce

So 1 GiB, 2GiB, 4GiB, 8GiB precisely.

@GregAC
Copy link
Contributor

GregAC commented Jan 17, 2020

I tried a run with the priority logic commented out of rv_plic_target (the theory being Vivado is doing something wrong with it, in 2018.3 this is a synthesis bug in 2019.2 it causes the large memory allocations and a crash) but same result.

@msfschaffner
Copy link
Contributor

Update: after closer netlist inspection, it looks like Vivado is dropping the whole target module for some reason in 2018.3. I can reproduce this behavior when synthesizing the rv_plic in isolation.

Moving to 2019.2 shows no improvement, neither.
I am inclined to file an issue with Xilinx...

@eunchan
Copy link
Contributor

eunchan commented Jan 17, 2020 via email

@msfschaffner
Copy link
Contributor

I am still bisecting the target module and I think I have found something. If that does not lead anywhere within the next 1-2h I will do what you suggested.

@msfschaffner
Copy link
Contributor

@GregAC, I think you ran into this (known) issue in 2019.2: https://www.xilinx.com/support/answers/73178.html

@msfschaffner
Copy link
Contributor

msfschaffner commented Jan 17, 2020

Ok I found the problem, which is likely a bug in Vivado.

If you look at the new binary tree implementation of rv_plic_target, it has two nested generate loops within which the different nodes of the tree are connected with each other.

Vivado doesn't seem to like the ternary statements on these lines:

assign sel = (!is_tree[c0] && is_tree[c1]) ? 1'b1 :
(is_tree[c0] && is_tree[c1] && max_tree[c1] > max_tree[c0]) ? 1'b1 :
1'b0;
// forwarding muxes
assign is_tree[pa] = (sel) ? is_tree[c1] : is_tree[c0];
assign id_tree[pa] = (sel) ? id_tree[c1] : id_tree[c0];
assign max_tree[pa] = (sel) ? max_tree[c1] : max_tree[c0];

If I rewrite this with bitwise ops mimicking a multiplexor, the module synthesizes without issues, and I can run the uart test with no problems.

I am going to push a patch for this and file a bug report to Xilinx.

@tjaychen
Copy link

tjaychen commented Jan 17, 2020 via email

@msfschaffner
Copy link
Contributor

Yes will do. The patch for this issue can be found here: #1364. PTAL

@sjgitty
Copy link
Contributor

sjgitty commented Jan 17, 2020

Great debugging and patience, @msfschaffner ! Let us know what Xilinx has to say.

@msfschaffner
Copy link
Contributor

Thanks everyone for helping track down this problem.
I have filed an issue with Xilinx:
https://forums.xilinx.com/t5/Synthesis/Simulation-Synthesis-Mismatch-with-Vivado-2018-3/m-p/1065923#M33849
Let's see what they respond...

In the meanwhile, the hotfix for this problem has been merged.
I would be great if somebody could confirm that the problem is resolved now.

@silvestrst
Copy link
Contributor Author

That's great, thank you @msfschaffner

@msfschaffner
Copy link
Contributor

Quick update:

This is a tooling issue (a signal gets optimized in the wrong way), and a Xilinx internal issue has been filed to get it fixed. In the meanwhile, follow the guidance provided here:
https://forums.xilinx.com/t5/Synthesis/Simulation-Synthesis-Mismatch-with-Vivado-2018-3/m-p/1066319/highlight/true#M33859

@asb
Copy link
Member

asb commented Jan 24, 2020

With #1364 merged to workaround this, and #1402 to track adding further testing, I think this issue can now be closed?

We could rewrite this issue to track the removal of the in-tree workaround but that seems messy/confusing. I propose:

  • @msfschaffner creates a new tracking issue for removing the workaround
  • We close this bug

@msfschaffner
Copy link
Contributor

Thanks @asb, agreed. I've opened another issue for this.

@asb
Copy link
Member

asb commented Jan 24, 2020

Thanks Michael, I like your optimism that this will be the only Vivado synthesis bug we encounter :)

silvestrst pushed a commit to silvestrst/opentitan that referenced this issue Feb 21, 2020
The purpose of this test is to validate external interrupt delivery from
peripheral to the target. The aim is not to test the entire PLIC or entirety
of the peripherals, but to ensure that two different IRQs can interrupt the
processor and be successfully handled. For the purpose of this test the UART
peripheral is used as the origin of the interrupts, and the interrupted target
is Ibex (the only target in current Earl Grey implementation).

This test ensures (in terms of UART RX Overflow and TX Empty IRQ sources, and
Ibex target):

* That PLIC getaway receives and handles an IRQ correctly.
* That PLIC Core and Target modules handle an IRQ correctly.
* That an IRQ can interrupt the target.
* That an IRQ can be cleared and a new IRQ can be processed.

The reason for introducing this test was an issues we had previously with the
IRQ delivery on the FPGA, see issue lowRISC#1355 for more details. This test can be
run by CI, and used manually to test the IRQs on an FPGA.

Fixes: lowRISC#1402

Signed-off-by: Silvestrs Timofejevs <silvestrst@lowrisc.org>
imphil pushed a commit that referenced this issue Feb 21, 2020
The purpose of this test is to validate external interrupt delivery from
peripheral to the target. The aim is not to test the entire PLIC or entirety
of the peripherals, but to ensure that two different IRQs can interrupt the
processor and be successfully handled. For the purpose of this test the UART
peripheral is used as the origin of the interrupts, and the interrupted target
is Ibex (the only target in current Earl Grey implementation).

This test ensures (in terms of UART RX Overflow and TX Empty IRQ sources, and
Ibex target):

* That PLIC getaway receives and handles an IRQ correctly.
* That PLIC Core and Target modules handle an IRQ correctly.
* That an IRQ can interrupt the target.
* That an IRQ can be cleared and a new IRQ can be processed.

The reason for introducing this test was an issues we had previously with the
IRQ delivery on the FPGA, see issue #1355 for more details. This test can be
run by CI, and used manually to test the IRQs on an FPGA.

Fixes: #1402

Signed-off-by: Silvestrs Timofejevs <silvestrst@lowrisc.org>
imphil added a commit to imphil/opentitan that referenced this issue May 25, 2021
Switch to Vivado 2020.2 as minimum requirement. This version fixes a
critical synthesis mismatch bug, as discussed in more detail at
https://forums.xilinx.com/t5/Synthesis/Simulation-Synthesis-Mismatch-with-Vivado-2018-3/m-p/1065923#M33849.

We did work around this Vivado bug in the past (see lowRISC#1355, lowRISC#1408),
but can avoid these workarounds now, as they collide slightly with
syntax that is works better for Verilator (lowRISC#6639).

Signed-off-by: Philipp Wagner <phw@lowrisc.org>
imphil added a commit to imphil/opentitan that referenced this issue Jul 5, 2021
Switch to Vivado 2020.2 as minimum requirement. This version fixes a
critical synthesis mismatch bug, as discussed in more detail at
https://forums.xilinx.com/t5/Synthesis/Simulation-Synthesis-Mismatch-with-Vivado-2018-3/m-p/1065923#M33849.

We did work around this Vivado bug in the past (see lowRISC#1355, lowRISC#1408),
but can avoid these workarounds now, as they collide slightly with
syntax that is works better for Verilator (lowRISC#6639).

Signed-off-by: Philipp Wagner <phw@lowrisc.org>
imphil added a commit that referenced this issue Jul 12, 2021
Switch to Vivado 2020.2 as minimum requirement. This version fixes a
critical synthesis mismatch bug, as discussed in more detail at
https://forums.xilinx.com/t5/Synthesis/Simulation-Synthesis-Mismatch-with-Vivado-2018-3/m-p/1065923#M33849.

We did work around this Vivado bug in the past (see #1355, #1408),
but can avoid these workarounds now, as they collide slightly with
syntax that is works better for Verilator (#6639).

Signed-off-by: Philipp Wagner <phw@lowrisc.org>
rasmus-madsen pushed a commit to rasmus-madsen/opentitan-1 that referenced this issue Aug 4, 2021
Switch to Vivado 2020.2 as minimum requirement. This version fixes a
critical synthesis mismatch bug, as discussed in more detail at
https://forums.xilinx.com/t5/Synthesis/Simulation-Synthesis-Mismatch-with-Vivado-2018-3/m-p/1065923#M33849.

We did work around this Vivado bug in the past (see lowRISC#1355, lowRISC#1408),
but can avoid these workarounds now, as they collide slightly with
syntax that is works better for Verilator (lowRISC#6639).

Signed-off-by: Philipp Wagner <phw@lowrisc.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component:FPGA FPGA related issues Type:Bug Bugs
Projects
None yet
Development

No branches or pull requests

7 participants