Skip to content

Commit

Permalink
Merge pull request #9 from leonardt/verilog-backend
Browse files Browse the repository at this point in the history
more refactoring of verilog codegen
  • Loading branch information
THofstee committed Oct 4, 2018
2 parents 7024b6f + 83c1303 commit 13b4725
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 221 deletions.
102 changes: 23 additions & 79 deletions silica/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
constant_fold, desugar_for_loops, specialize_evals, inline_yield_from_functions
from silica.visitors import collect_names
import silica.verilog as verilog
from .verilog import get_width_str
from .width import get_width
from .memory import MemoryType
from silica.transformations.specialize_arguments import specialize_arguments
Expand Down Expand Up @@ -64,26 +63,6 @@ def get_input_width(type_):
raise NotImplementedError(type_)


def make_io_string(inputs, outputs, width_table):
io_strings = []
for output in outputs:
width = width_table[output]
if width is None:
io_strings.append(f"output {output}")
else:
io_strings.append(f"output [{width_table[output] - 1}:0] {output}")

if inputs:
for input_, type_ in inputs.items():
if isinstance(type_, m.BitKind):
io_strings.append(f"input {input_}")
elif isinstance(type_, m.ArrayKind) and isinstance(type_.T, m.BitKind):
io_strings.append(f"input [{len(type_)-1}:0] {input_}")
else:
raise NotImplementedError(type_)
return ", ".join(io_strings)


def compile(coroutine, file_name=None, mux_strategy="one-hot", output='verilog', strategy="by_statement"):
if not isinstance(coroutine, Coroutine):
raise ValueError("silica.compile expects a silica.Coroutine")
Expand Down Expand Up @@ -135,22 +114,19 @@ def compile(coroutine, file_name=None, mux_strategy="one-hot", output='verilog',
outputs += (collect_names(path[-1].value, ctx=ast.Load), )
assert all(outputs[1] == output for output in outputs[1:]), "Yield statements must all have the same outputs except for the first"
outputs = outputs[1]
io_string = make_io_string(coroutine._inputs, outputs, width_table)
states = cfg.states
num_yields = cfg.curr_yield_id
num_states = len(states)
initial_values = {}
initial_basic_block = False
sub_coroutines = []
# cfg.render()
verilog_source = ""
for node in cfg.paths[0][:-1]:
if isinstance(node, HeadBlock):
for statement in node:
if ast_utils.is_call(statement.value) and ast_utils.is_name(statement.value.func) and statement.value.func.id == "coroutine_create":
sub_coroutine = eval(astor.to_source(statement.value.args[0]), func_globals, func_locals)
raise NotImplementedError()
verilog_source += verilog_compile(sub_coroutine(), func_globals, func_locals)
statement.value.func = ast.Name(sub_coroutine._name, ast.Load())
statement.value.args = []
sub_coroutines.append((statement, sub_coroutine))
Expand All @@ -172,28 +148,25 @@ def compile(coroutine, file_name=None, mux_strategy="one-hot", output='verilog',
raise NotImplementedError("add ce to module decl")

# declare module and ports
module = vg.Module(module_name)
for o in outputs:
module.Output(o, width_table.get(o, 1))
if coroutine._inputs:
for i,t in coroutine._inputs.items():
if isinstance(t, m.BitKind):
module.Input(i)
else:
module.Input(i, t.N)
module.Input("CLK")
verilog_source += f"""
module {module_name} ({io_string}, input CLK);
"""
ctx = verilog.Context(module_name)

def get_len(t):
try:
return len(t)
except Exception:
return 1

inputs = { i : get_len(t) for i,t in coroutine._inputs.items() }
inputs["CLK"] = 1
outputs = { o : width_table.get(o, 1) or 1 for o in outputs }
ctx.declare_ports(inputs, outputs)

# declare wires
for var in cfg.replacer.id_counter:
width = width_table[var]
for i in range(cfg.replacer.id_counter[var] + 1):
if f"{var}_{i}" not in registers:
width_str = get_width_str(width)
module.Wire(f"{var}_{i}", width)
verilog_source += f" wire {width_str} {var}_{i};\n"
ctx.declare_wire(f"{var}_{i}", width)

for (name, index), value in cfg.replacer.array_stores.items():
width = width_table[name]
Expand All @@ -212,62 +185,33 @@ def compile(coroutine, file_name=None, mux_strategy="one-hot", output='verilog',
for register in registers:
width = width_table[register]
if isinstance(width, MemoryType):
module.Reg(register, width.width, width.height)
width_str = get_width_str(width.width)
verilog_source += f" reg {width_str} {register} [0:{width.height - 1}];\n"
ctx.declare_reg(register, width.width, width.height)
else:
module.Reg(register, width)
width_str = get_width_str(width)
verilog_source += f" reg {width_str} {register};\n"
ctx.declare_reg(register, width)

init_strings = []
init = module.Initial()
for key, value in initial_values.items():
if value is not None:
init.add(
verilog.get_by_name(module, key)(value)
)
init_strings.append(f"{key} = {value};")
init_body = [ctx.assign(ctx.get_by_name(key), value) for key,value in initial_values.items() if value is not None]

if cfg.curr_yield_id > 1:
module.Reg("yield_state", (cfg.curr_yield_id - 1).bit_length(), initval=0)
verilog_source += f" reg [{(cfg.curr_yield_id - 1).bit_length() - 1}:0] yield_state;\n"
init_strings.append(f"yield_state = 0;")
ctx.declare_reg("yield_state", (cfg.curr_yield_id - 1).bit_length())
init_body.append(ctx.assign(ctx.get_by_name("yield_state"), 0))

# TODO: need to do this
if initial_basic_block:
for statement in states[0].statements:
verilog.process_statement(statement)
# init_body.append(ctx.translate(statement)) # TODO: redefinition bug?
# temp_var_promoter.visit(statement)
init_strings.append(astor.to_source(statement).rstrip() + ";")

init_string = '\n '.join(init_strings)
verilog_source += f"""
initial begin
{init_string}
end
"""
ctx.initial(init_body)

raddrs = {}
waddrs = {}
wdatas = {}
wens = {}
if initial_basic_block:
states = states[1:]
always_source, temp_var_source = verilog.compile_states(module, states, cfg.curr_yield_id == 1, width_table, strategy)
verilog_source += temp_var_source + always_source
verilog_source += "\n end\nendmodule"
verilog_source = verilog_source.replace("True", "1")
verilog_source = verilog_source.replace("False", "0")
verilog.compile_states(ctx, states, cfg.curr_yield_id == 1, width_table, strategy)
# cfg.render()

print(module.to_verilog())
print(verilog_source)

# with open(file_name, "w") as f:
# f.write(verilog_source)
# return m.DefineFromVerilog(verilog_source, type_map={"CLK": m.In(m.Clock)})[-1]

with open(file_name, "w") as f:
f.write(module.to_verilog())
return m.DefineFromVerilog(module.to_verilog(), type_map={"CLK": m.In(m.Clock)})[-1]
f.write(ctx.to_verilog())
return m.DefineFromVerilog(ctx.to_verilog(), type_map={"CLK": m.In(m.Clock)})[-1]
2 changes: 1 addition & 1 deletion silica/coroutine.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class _Coroutine(Coroutine):
else:
class _Coroutine(Coroutine):
_definition = func
_inputs = inputs
_inputs = {}
_defn_locals = defn_locals
_name = func.__name__
return _Coroutine
Expand Down
Loading

0 comments on commit 13b4725

Please sign in to comment.