-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
243 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import types | ||
import magma as m | ||
import silica.verilog as verilog | ||
import inspect | ||
from silica.visitors import collect_stores | ||
from silica.analysis import CollectInitialWidthsAndTypes | ||
from silica.type_check import to_type_str | ||
from silica.width import get_io_width | ||
import ast | ||
import veriloggen as vg | ||
|
||
|
||
class ReturnReplacer(ast.NodeTransformer): | ||
def visit_Return(self, node): | ||
if isinstance(node.value, ast.Tuple): | ||
raise NotImplementedError() | ||
return ast.Assign([ast.Name("O", ast.Store())], node.value) | ||
|
||
|
||
def function(fn : types.FunctionType): | ||
""" TODO: Do implicit conversion of Python types to BitVector """ | ||
return fn | ||
|
||
|
||
def compile_function(fn : types.FunctionType, file_name : str): | ||
stack = inspect.stack() | ||
func_locals = stack[1].frame.f_locals | ||
func_globals = stack[1].frame.f_globals | ||
tree = m.ast_utils.get_func_ast(fn) | ||
ctx = verilog.Context(tree.name) | ||
width_table = {} | ||
type_table = {} | ||
|
||
def get_len(t): | ||
try: | ||
return len(t) | ||
except Exception: | ||
return 1 | ||
|
||
|
||
inputs = inspect.getfullargspec(fn).annotations | ||
for input_, type_ in inputs.items(): | ||
type_table[input_] = to_type_str(type_) | ||
width_table[input_] = get_io_width(type_) | ||
|
||
inputs = { i : get_len(t) for i,t in inputs.items() } | ||
output = inspect.signature(fn).return_annotation | ||
assert not isinstance(output, tuple), "Not implemented" | ||
type_table["O"] = to_type_str(output) | ||
width_table["O"] = get_io_width(output) | ||
outputs = { "O" : get_len(output) } | ||
|
||
CollectInitialWidthsAndTypes(width_table, type_table, func_locals, func_globals).visit(tree) | ||
|
||
ctx.declare_ports(inputs, outputs) | ||
|
||
stores = collect_stores(tree) | ||
for store in stores: | ||
ctx.declare_wire(store, width_table[store]) | ||
|
||
tree = ReturnReplacer().visit(tree) | ||
|
||
ctx.module.Always(vg.SensitiveAll())([ctx.translate(s) for s in tree.body]) | ||
|
||
with open(file_name, "w") as f: | ||
f.write(ctx.to_verilog()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import silica as si | ||
|
||
|
||
# TODO: These were adapted from magma's SSA tests, perhaps we can find a nice | ||
# way to reuse test functions? | ||
def test_basic(): | ||
@si.function | ||
def basic_if(I: si.Bits(2), S: si.Bit) -> si.Bit: | ||
if S: | ||
x = I[0] | ||
else: | ||
x = I[1] | ||
return x | ||
|
||
si.compile_function(basic_if, file_name="tests/build/basic_if.v") | ||
with open("tests/build/basic_if.v", "r") as f: | ||
result = f.read() | ||
print(result) | ||
assert result == """\ | ||
module basic_if | ||
( | ||
output O, | ||
input return, | ||
input [2-1:0] I, | ||
input S | ||
); | ||
wire x; | ||
always @(*) begin | ||
if(S) begin | ||
x = I[0]; | ||
end else begin | ||
x = I[1]; | ||
end | ||
O = x; | ||
end | ||
endmodule | ||
""" | ||
|
||
|
||
def test_default(): | ||
@si.function | ||
def default(I: si.Bits(2), S: si.Bit) -> si.Bit: | ||
x = I[1] | ||
if S: | ||
x = I[0] | ||
return x | ||
|
||
si.compile_function(default, file_name="tests/build/default.v") | ||
with open("tests/build/default.v", "r") as f: | ||
result = f.read() | ||
print(result) | ||
assert result == """\ | ||
module default | ||
( | ||
output O, | ||
input return, | ||
input [2-1:0] I, | ||
input S | ||
); | ||
wire x; | ||
always @(*) begin | ||
x = I[1]; | ||
if(S) begin | ||
x = I[0]; | ||
end | ||
O = x; | ||
end | ||
endmodule | ||
""" | ||
|
||
|
||
def test_nested(): | ||
@si.function | ||
def nested(I: si.Bits(4), S: si.Bits(2)) -> si.Bit: | ||
if S[0]: | ||
if S[1]: | ||
x = I[0] | ||
else: | ||
x = I[1] | ||
else: | ||
if S[1]: | ||
x = I[2] | ||
else: | ||
x = I[3] | ||
return x | ||
|
||
si.compile_function(nested, file_name="tests/build/nested.v") | ||
with open("tests/build/nested.v", "r") as f: | ||
result = f.read() | ||
print(result) | ||
assert result == """\ | ||
module nested | ||
( | ||
output O, | ||
input return, | ||
input [4-1:0] I, | ||
input [2-1:0] S | ||
); | ||
wire x; | ||
always @(*) begin | ||
if(S[0]) begin | ||
if(S[1]) begin | ||
x = I[0]; | ||
end else begin | ||
x = I[1]; | ||
end | ||
end else if(S[1]) begin | ||
x = I[2]; | ||
end else begin | ||
x = I[3]; | ||
end | ||
O = x; | ||
end | ||
endmodule | ||
""" |