YosysHQ / apicula

Project Apicula 🐝: bitstream documentation for Gowin FPGAs
MIT License
485 stars 67 forks source link

Bug in gowin_unpack.py? #288

Open pecostm32 opened 2 days ago

pecostm32 commented 2 days ago

I ran into a snag with the output of gowin_unpack.py when trying to synthesize it in the Gowin IDE.

The IDE fails with an error on ALU definitions like this one:

ALU R2C6_ALU_0 ( .SUM(R2C6_F0), .CIN(R2C6_CIN0), .I2(R2C6_C0), .COUT(R2C6_CIN1), .I0(R2C6_B0), .I1(R2C6_D0), .I3(R2C6_A0) );

ERROR (EX3990) : Cannot find port 'I2' on this module("/home/peter/Data/Gowin_projects/GW2AR_PSRAM/src/psram_control.v":476634)

In the output for simulation, generated by the IDE, it looks like this:

ALU \u_psram_top/u_psram_top_0/u_psram_wd/step_cry_0[6] ( .I0(GND), .I1(\u_psram_top/u_psram_top_0/u_psram_wd/step [6]), .I3(GND), .CIN(\u_psram_top/u_psram_top_0/u_psram_wd/step_cry [5]), .COUT(\u_psram_top/u_psram_top_0/u_psram_wd/step_cry [6]), .SUM(\u_psram_top/u_psram_top_0/u_psram_wd/step_s [6]) );

I have not looked at the python code to see why this is happening as I fear it will be a bit deeper than the other problems found.

Any ideas?

yrabbit commented 2 days ago

Now here's where it gets interesting.

It's easy to fix, but it raises a question about the main purpose of UNPACK - is it a research tool or can its output be fed back to the IDE?

In the case of ALU, without knowing where I2 is connected, speculating about internal mechanisms would be more fun ;) https://github.com/YosysHQ/apicula/blob/master/doc/alu.md

So here we need to make a purely administrative decision about the goals.

pecostm32 commented 2 days ago

I'm looking into the FPGA configuration used in the Hantek DSO2000 series of oscilloscopes and had hoped that the output of the unpack tool was usable for both in the IDE and simulation.

I will look at where the wire connected to I2 goes.

Fun part, my first discovery is that the used pins for the additional internal memory do not concur with what the IDE generates for both SDRAM and PSRAM. So it is still a guess as to which FPGA it is. The chip is marked Lemontree instead of Gowin and does not have a type specification like GW2AR, but the bitstream matches the format of the Gowin devices and the ID is the one for the GW2AR-18.

It will be a time consuming project, but as a retired engineer I have all the time in the world.

pepijndevos commented 2 days ago

That's a very interesting use of the tool!

We mostly use it to verify our understanding of the bitstream. If we can correctly interpret a vendor bitstream and it matches what we generate ourselves, we have a pretty good idea that our understanding is correct.

We actually never roundtrip the bitstream completely through unpacking and repacking. Though I've had a few cases where it would have been useful. It could also be an useful test to see if repeatedly unpacking and packing a bitstream produces the same result.

We already have a few feature flags that allow us to use unpacking during fuzzing while we haven't built a complete database yet.

What yrabbit is saying is also true though, there is some value in having the unpacked code represent the bitstream as it is rather than the code that generated it.

In this case, the alu is a regular lut with one unused port that very much exists in hardware. Preserving this can be useful for weird hacks and debugging.

I think it's valuable to support third party bitstream reverse engineering.

So I'm in favour of being able to simulate and roundtrip unpacked bitstreams, but not at the cost of accurate unpacking.

I think in this case, nothing stops us from adding the hidden port to our yosys simlib.

Note that for full roundtrip we need to annotate locations in a way yosys and nextpnr understand and convert the verilog to json.

Sent from Proton Mail Android

-------- Original Message -------- On 24/10/2024 08:16, pecostm32 wrote:

I'm looking into the FPGA configuration used in the Hantek DSO2000 series of oscilloscopes and had hoped that the output of the unpack tool was usable for both in the IDE and simulation.

I will look at where the wire connected to I2 goes.

Fun part, my first discovery is that the used pins for the additional internal memory do not concur with what the IDE generates for both SDRAM and PSRAM. So it is still a guess as to which FPGA it is. The chip is marked Lemontree instead of Gowin and does not have a type specification like GW2AR, but the bitstream matches the format of the Gowin devices and the ID is the one for the GW2AR-18.

It will be a time consuming project, but as a retired engineer I have all the time in the world.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>

pecostm32 commented 2 days ago

I looked at where the wire is connected.

wire R2C6_X04; wire R2C6_C0; assign R2C6_C0 = R2C6_X04; assign R2C6_C1 = R2C6_X04; assign R2C6_C2 = R2C6_X04; assign R2C6_C3 = R2C6_X04;

but R2C6_X04 is an open wire. In another design it was connected to vcc.

In this case the ALU mode is zero, so add, and the flipflop is used too, which might make it a counter or an address register. In the design I'm trying to reverse I also saw mode 9 for multiplication.

I noticed that in the listings for a LUT, the content of the memory is given, but for an ALU it is not. I did see the other issue about the ALU and mentioning about the possible extended use of the lookup table still in use. I assume that the ALU mode is set with separate configuration bits and that the LUT memory is filled with data needed to make the ALU function?

defparam R2C6_ALU_2.ALU_MODE = 0; defparam R2C7_LUT4_0.INIT = 16'h1540;

When I worked on reversing the Anlogic FPGA design I went through a lot of stages to improve on trying to get as close as possible to the original design, which is quite hard to do. Also started with making test designs in the IDE to see what the output became and then try to go back to the IDE with the reversed design. It hardly ever came back to the same output, simply because the place and route code would stuff it in different parts of the FPGA. Maybe with a constraint on where the logic needs to be placed it might result in the same bitstream.

Even though not entirely new to FPGA design the use of HDL and constraint files was new to me. So it was also a learning project at that. In the end I did succeed in getting verilog output at some higher level then the primitives format gowin_unpack outputs, but the in between steps have used a similar primitives format. I will need to write something similar for this project, but it is very nice to have your unpack tool to start with.

I agree that unpacking should reflect what is actually in the bitstream, and I can simply write a filter to get rid of the I2 node.

Already wrote some code to revert the IO block information back to the external pin information, which is needed to be able to get a grip on the design. For the Anlogic FPGA (FNIRSI scope) I also had a good inside in the functionality that made things easier. (I reverse engineered the scope software first) For the Gowin one (Hantek scope) I don't have this information, but I did reverse engineer the schematic of the scope, so not totally blind.

My code will eventually be open sourced, but won't be for general reverse engineering as I'm specifically targeting this GW2AR-18 device.

yrabbit commented 1 day ago

I noticed that in the listings for a LUT, the content of the memory is given, but for an ALU it is not.

yeah, because gowin_unpack had a “--noalu” switch a long time ago (and may still have it) that made all ALUs show as LUTs. It helped to understand how arithmetic works.

I assume that the ALU mode is set with separate configuration bits and that the LUT memory is filled with data needed to make the ALU function?

right, and always in pairs - these configuration bits do not distinguish between even and odd ALU/LUT and switch the mode of both at once.