chipsalliance / f4pga-examples

Example designs showing different ways to use F4PGA toolchains.
https://f4pga-examples.readthedocs.io
Apache License 2.0
266 stars 78 forks source link

Symbiflow-classroom: Initialization of memories using $readmemh() #281

Open nelsobe opened 2 years ago

nelsobe commented 2 years ago

SYMBIFLOW-CLASSROOM-PROJECT

Using Yosys front end.

The following code does NOT initialize the memory:

    // Load the Instruction Memory
    if (TEXT_MEMORY_FILENAME == "") begin
        $display("**** Top-Level I/O System: No instruction memory defined");
        $finish;
    end
    else begin
        // Initialize memory with NOPs
        for (i = 0; i < INSTRUCTION_WORDS; i=i+1)
            inst_memory[i] = NOP_INSTRUCTION;
        // Update memory with contents of memory file
        $readmemh(TEXT_MEMORY_FILENAME,inst_memory);
    end

Experimentation shows that the testing of the TEXT_MEMORY_FILENAME works just fine. The problem turns out to be the for loop which initializes the memory to NOP_INSTRUCTION values before the #readmemh(). Commenting out the for loop makes everything work. However this is code that works just fine with Vivado.

rkapuscik commented 2 years ago

Thank you for reporting this. Can you confirm that this does not work in either frontend? If so, it would probably be a problem in Yosys itself and worth reporting in its repository. Alternatively, do you have a complete test case we could use to look into this?

nelsobe commented 2 years ago

@rkapuscik

I am unsure how to get the latest surelog with the f4pga-examples tools - thus my question on #269.

However, attached is a full test case up through bitfile showing that the $readmem is ignored when the initialization loop is included. This is for the Yosys front end.

readmem.zip

rkapuscik commented 2 years ago

Thanks for the test case. The error is indeed in Yosys itself - both frontends parse the loop and $readmemh call and generate the AST, but the simplify step in Yosys incorrectly removes some of the nodes. Unfortunately it's not trivial (if possible) to prevent that in a frontend.

As a workaround, could you create a complete memory file to be loaded (with the NOPs)? It should be fairly easy to script.

nelsobe commented 2 years ago

Thanks for the reply. Yes, we did do a workaround as you suggest. Interestingly, I never would have thought to put anything in an initial block other than a $readmem() call. But, one of the other faculty did - that is why we are having lots of people's designs be part of our testing...