phanrahan / magma

magma circuits
Other
244 stars 23 forks source link

Importing verilog modules with parametrized types (width) #296

Open leonardt opened 6 years ago

leonardt commented 6 years ago

I remembered one idea on how to do this based on our meeting with priyanka

Supposed we had this circuit

module coreir_add #(parameter width=1) (
  input [width-1:0] in0,
  input [width-1:0] in1,
  output [width-1:0] out
);
  assign out = in0 + in1;

endmodule

Create a function

def DefineCoreirAdd(width):
    verilog = """
module coreir_add_${width-1} (
  input [${width-1}:0] in0,
  input [${width-1}:0] in1,
  output [${width-1}:0] out
);
  coreir_add #(.width(${width})) inst0(.in0(in0), .in1(in1), .out(out));

endmodule //coreir_add
"""
    return DefineFromVerilog(mako.template.Template(verilog).render(width=width)

Basically, stub out a version of the interface with the parameters replaced with mako template parameters. Specialize the template parameters so we can import them into magma. Then the verilog body just instances the parameterized module with the template parameters and passes through the wires.

Alternatively, rather than trying to generate the above verilog module, we could instead parse the parameterized verilog module and try to generate a magma module, then just set the definition to be the verilog string with the instancing and wiring of the parameterized circuit. Not sure if it'll be easier to generate the modified verilog from the original, or to just parse the type signature into magma types.

phanrahan commented 6 years ago

That will work.

For simple parameter interpolation, we can also use python's formatted strings.

def DefineCoreirAdd(width):
    return DefineFromVerilog( f"""
module coreir_add_{width-1} (
  input [{width-1}:0] in0,
  input [{width-1}:0] in1,
  output [{width-1}:0] out
);
  coreir_add #(.width({width})) inst0(.in0(in0), .in1(in1), .out(out));
endmodule //coreir_add
""")