Skip to content

Commit

Permalink
shim: fix, add forgotten generator
Browse files Browse the repository at this point in the history
  • Loading branch information
widlarizer committed Jul 11, 2024
1 parent 5ca78ae commit 6922a68
Showing 1 changed file with 183 additions and 0 deletions.
183 changes: 183 additions & 0 deletions kernel/shim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
from pathlib import Path

with open("kernel/constids.inc") as f:
X = set([line[2:-2] for line in f.readlines() if len(line) > 2])

# f.write(X)
# ValidConstID = NewType('ValidConstID', str)


class ValidConstID(str):
# https://stackoverflow.com/questions/69844072/why-isnt-python-newtype-compatible-with-isinstance-and-type
def __new__(cls, *args, **kwargs):
return str.__new__(cls, *args, **kwargs)


def id(str):
assert str in X
return ValidConstID(str)


class CellType():
name: str
inputs: list[ValidConstID, ValidConstID | int]
outputs = list[ValidConstID, ValidConstID | int]
other_params = list[ValidConstID, type]

def __init__(self, name, inputs, outputs, other_params, add_wire_width_expr):
self.name = name
self.inputs = inputs
self.outputs = outputs
self.other_params = other_params
self.add_wire_width_expr = add_wire_width_expr
self.inputs.sort()
self.outputs.sort()
self.other_params.sort()

def arg_inputs(self, call=False):
s = ""
if call:
s += "".join(map(
lambda inp: f"sig_{inp[0].lower()}, ", self.inputs))
else:
s += "".join(map(
lambda inp: f"const RTLIL::SigSpec &sig_{inp[0].lower()}, ", self.inputs))
return s

def arg_outputs(self, call=False):
s = ""
if call:
s += "".join(map(
lambda outp: f"sig_{outp[0].lower()}, ", self.outputs))
else:
s += "".join(map(
lambda outp: f"const RTLIL::SigSpec &sig_{outp[0].lower()}, ", self.outputs))
return s

def emit_add_h(self, filename):

def _argumentize_param(param):
is_only_one_param_signed = len(
list(filter(lambda x: "_SIGNED" in x[0], self.other_params))) == 1
if "_SIGNED" in param and is_only_one_param_signed:
return "is_signed = false"
else:
return param.lower()

with open(filename, 'a') as f:
f.write(
f"RTLIL::Cell* add{self.name.title()}(RTLIL::IdString name, ")
f.write(self.arg_inputs() + self.arg_outputs())
f.write("".join(
map(lambda par: f"{par[1].__name__} {_argumentize_param(par[0])}, ", self.other_params)))
f.write("const std::string &src = \"\");\n")

def emit_add_cc(self, filename):

def _argumentize_param(param):
is_only_one_param_signed = len(
list(filter(lambda x: "_SIGNED" in x[0], self.other_params))) == 1
if "_SIGNED" in param and is_only_one_param_signed:
return "is_signed"
else:
return param.lower()

with open(filename, 'a') as f:
f.write(
f"RTLIL::Cell* RTLIL::Module::add{self.name.title()}(RTLIL::IdString name, ")
f.write(self.arg_inputs() + self.arg_outputs())
f.write("".join(
map(lambda par: f"{par[1].__name__} {_argumentize_param(par[0])}, ", self.other_params)))
f.write("const std::string &src)\n")

f.write("{\n")
f.write(
f"\tRTLIL::Cell *cell = addCell(name, ID(${self.name}));\n")

for param in self.other_params:
f.write(
f"\tcell->parameters[ID::{param[0]}] = {_argumentize_param(param[0])};\n")

for input, width in self.inputs:
if isinstance(width, ValidConstID):
f.write(
f"\tcell->parameters[ID::{width}] = sig_{input.lower()}.size();\n")

for output, width in self.outputs:
if isinstance(width, ValidConstID):
f.write(
f"\tcell->parameters[ID::{width}] = sig_{output.lower()}.size();\n")

for input, _ in self.inputs:
f.write(
f"\tcell->setPort(ID::{input}, sig_{input.lower()});\n")
for output, _ in self.outputs:
f.write(
f"\tcell->setPort(ID::{output}, sig_{output.lower()});\n")
f.write("\tcell->set_src_attribute(src);\n")
f.write("\treturn cell;\n")
f.write("}\n\n")

if self.add_wire_width_expr:
f.write(
f"RTLIL::SigSpec RTLIL::Module::{self.name.title()}(RTLIL::IdString name, {self.arg_inputs()}")
f.write("".join(
map(lambda par: f"{par[1].__name__} {_argumentize_param(par[0])}, ", self.other_params)))
f.write("const std::string &src) {\n")
f.write(
f"\tRTLIL::SigSpec sig_y = addWire(NEW_ID, {self.add_wire_width_expr});\n")
f.write(
f"\tadd{self.name.title()}(name, {self.arg_inputs(call=True)}{self.arg_outputs(call=True)}")
f.write("".join(
map(lambda par: f"{_argumentize_param(par[0])}", self.other_params)))
f.write(f", src);\n")
f.write("\treturn sig_y;\n")
f.write("}\n\n")
# _func(const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed, const std::string &src) { \
# RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \
# add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \
# return sig_y; \
# }


def unary(name):
inputs = [(id("A"), id("A_WIDTH"))]
outputs = [(id("Y"), id("Y_WIDTH"))]
other_params = [(id("A_SIGNED"), bool)]
add_wire_width_expr = "sig_a.size()"
return CellType(name, inputs, outputs, other_params, add_wire_width_expr)


celltypes = []
celltypes += [unary("pos")]
celltypes += [unary("neg")]
celltypes += [unary("not")]

shim_headers = Path("kernel/adds.shim.h")
shim_headers.unlink(missing_ok=True)
shim_src = Path("kernel/adds.shim.cc")
shim_src.unlink(missing_ok=True)


def emit_boilerplate():
warning = "/* Generated by shim.py, do not modify */\n"
with open(shim_headers, 'a') as f:
f.write(warning)
f.write('#ifndef SHIM_H\n')
f.write('#define SHIM_H\n')
f.write('#include "kernel/yosys.h"\n')
f.write('#endif /* SHIM_H */\n')

with open(shim_src, 'a') as f:
f.write(warning)
f.write('#include "kernel/yosys.h"\n')
f.write("USING_YOSYS_NAMESPACE\n")


emit_boilerplate()

for celltype in celltypes:
celltype.emit_add_h(shim_headers)

for celltype in celltypes:
celltype.emit_add_cc(shim_src)

0 comments on commit 6922a68

Please sign in to comment.