3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-24 01:25:33 +00:00

shim: fix, add forgotten generator

This commit is contained in:
Emil J. Tywoniak 2024-07-11 14:46:39 +02:00
parent 5ca78aec37
commit 6922a68cea

183
kernel/shim.py Normal file
View file

@ -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)