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:
parent
5ca78aec37
commit
6922a68cea
1 changed files with 183 additions and 0 deletions
183
kernel/shim.py
Normal file
183
kernel/shim.py
Normal 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)
|
Loading…
Add table
Add a link
Reference in a new issue