From 6922a68cea28c058393a2a65a7ed783c3c5f278b Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 11 Jul 2024 14:46:39 +0200 Subject: [PATCH] shim: fix, add forgotten generator --- kernel/shim.py | 183 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 kernel/shim.py diff --git a/kernel/shim.py b/kernel/shim.py new file mode 100644 index 00000000000..eb3f1a38f96 --- /dev/null +++ b/kernel/shim.py @@ -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)