-
Notifications
You must be signed in to change notification settings - Fork 903
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5ca78ae
commit 6922a68
Showing
1 changed file
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |