[libre-riscv-dev] Migen Conversions and Update

Daniel Benusovich flyingmonkeys1996 at gmail.com
Wed Jan 2 05:13:56 GMT 2019


Good evening!

I have been silent for while but not in vain! I have gotten a much better
hold on Verilog, Python, and Migen in the past couple months. An arduous
task indeed as I have never used Verilog before and very sparingly Python.

Anyways I have done my best to port over Jacob's ALU first as a test run. I
have attached the files (I know the mailing list wont have them but I will
put in some choice snippets for the curious bits).

I found that Migen does its best to keep things clean when converting from
python to verilog and while some conversion are perfect the syntax can be a
bit odd.

For example, the ternary operation ( a ? b : c) is replicated via a
function Mux(a, b, c) which I found quite odd as that is not mentioned
anywhere. I only found out after converting it over in despair.

The bigger problem is that I have not yet found a way to convert functions
from python to verilog. The functions are executed (in python) and the
result is then converted into verilog.

Example.py
> def add(a,b):
>     return a + b
>
> //Various garbage here
> ...
> a.eq(add(0,1))
> //More various garbage here
> ...
>
> results in
> Example.v
> assign a = 1
>

which was not my dream! Functionality is provided to get around it but it
is not nearly as pretty.

A snippet from the code is as follow
cpu_alu.py

> Case(funct3, {
>                 0: result.eq(add_sub_result),
>                 1: result.eq(shift_left_result),
>                 2: result.eq(lt_result),
>                 3: result.eq(lt_result),
>                 4: result.eq(xor_result),
>                 5: result.eq(shift_right_result),
>                 6: result.eq(or_result),
>                 7: result.eq(and_result),
>                 "default": result.eq(0xFFFFFFFF),
>             })
>

cpu_alu.v

> always @(*) begin
>     result <= 32'd0;
>     case (funct3)
>         1'd0: begin
>             result <= add_sub_result;
>         end
>         1'd1: begin
>             result <= shift_left_result;
>         end
>         2'd2: begin
>             result <= lt_result;
>         end
>         2'd3: begin
>             result <= lt_result;
>         end
>         3'd4: begin
>             result <= xor_result;
>         end
>         3'd5: begin
>             result <= shift_right_result;
>         end
>         3'd6: begin
>             result <= or_result;
>         end
>         3'd7: begin
>             result <= and_result;
>         end
>         default: begin
>             result <= 32'd4294967295;
>         end
>     endcase
> end
>

This physically hurt me as Jacob's function was much prettier to look at
(in Verilog). It seems to be hard without breaking into additional modules
(which is fine but I wanted to keep it to the same file count). In
addition, i have not discovered a way to convert 'X' through as a default
value (forgive my ignorance) if it is possible at all.

A couple nice things after all the bad is no need to declare inputs or
outputs! It is all nicely handled which is a nice change of pace. After
creating a module it can be easily referenced like any python object which
is also very helpful as referencing internal signals and wires is a breeze.

I will continue to work on the conversion unless something else comes up.
Do let me know if anything needs to be done coding: the instructions,
scoreboard, or implementation of Tomusulo's algorithm you are talking about
in the mailing list and google discussion. If you could send me some
references I would be happy to take a jab it.

Happy new year!

Daniel Benusovich


More information about the libre-riscv-dev mailing list