mirror of https://github.com/YosysHQ/yosys.git
functinoal: twines
This commit is contained in:
parent
5b5e7ce771
commit
d8e09f4e0c
|
|
@ -44,7 +44,8 @@ const char *reserved_keywords[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Id> struct CxxScope : public Functional::Scope<Id> {
|
template<typename Id> struct CxxScope : public Functional::Scope<Id> {
|
||||||
CxxScope() {
|
CxxScope(Design *design = nullptr) {
|
||||||
|
this->design = design;
|
||||||
for(const char **p = reserved_keywords; *p != nullptr; p++)
|
for(const char **p = reserved_keywords; *p != nullptr; p++)
|
||||||
this->reserve(*p);
|
this->reserve(*p);
|
||||||
}
|
}
|
||||||
|
|
@ -71,14 +72,15 @@ using CxxWriter = Functional::Writer;
|
||||||
|
|
||||||
struct CxxStruct {
|
struct CxxStruct {
|
||||||
std::string name;
|
std::string name;
|
||||||
dict<IdString, CxxType> types;
|
dict<TwineRef, CxxType> types;
|
||||||
CxxScope<IdString> scope;
|
CxxScope<TwineRef> scope;
|
||||||
CxxStruct(std::string name) : name(name)
|
Design *design;
|
||||||
|
CxxStruct(std::string name, Design *design) : name(name), scope(design), design(design)
|
||||||
{
|
{
|
||||||
scope.reserve("fn");
|
scope.reserve("fn");
|
||||||
scope.reserve("visit");
|
scope.reserve("visit");
|
||||||
}
|
}
|
||||||
void insert(IdString name, CxxType type) {
|
void insert(TwineRef name, CxxType type) {
|
||||||
scope(name, name);
|
scope(name, name);
|
||||||
types.insert({name, type});
|
types.insert({name, type});
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +96,7 @@ struct CxxStruct {
|
||||||
f.print("\t\t}}\n");
|
f.print("\t\t}}\n");
|
||||||
f.print("\t}};\n\n");
|
f.print("\t}};\n\n");
|
||||||
};
|
};
|
||||||
std::string operator[](IdString field) {
|
std::string operator[](TwineRef field) {
|
||||||
return scope(field, field);
|
return scope(field, field);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -151,8 +153,8 @@ template<class NodePrinter> struct CxxPrintVisitor : public Functional::Abstract
|
||||||
void arithmetic_shift_right(Node, Node a, Node b) override { print("{}.arithmetic_shift_right({})", a, b); }
|
void arithmetic_shift_right(Node, Node a, Node b) override { print("{}.arithmetic_shift_right({})", a, b); }
|
||||||
void mux(Node, Node a, Node b, Node s) override { print("{2}.any() ? {1} : {0}", a, b, s); }
|
void mux(Node, Node a, Node b, Node s) override { print("{2}.any() ? {1} : {0}", a, b, s); }
|
||||||
void constant(Node, RTLIL::Const const & value) override { print("{}", cxx_const(value)); }
|
void constant(Node, RTLIL::Const const & value) override { print("{}", cxx_const(value)); }
|
||||||
void input(Node, IdString name, IdString kind) override { log_assert(kind == TW($input)); print("input.{}", input_struct[name]); }
|
void input(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($input)); print("input.{}", input_struct[name]); }
|
||||||
void state(Node, IdString name, IdString kind) override { log_assert(kind == TW($state)); print("current_state.{}", state_struct[name]); }
|
void state(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($state)); print("current_state.{}", state_struct[name]); }
|
||||||
void memory_read(Node, Node mem, Node addr) override { print("{}.read({})", mem, addr); }
|
void memory_read(Node, Node mem, Node addr) override { print("{}.read({})", mem, addr); }
|
||||||
void memory_write(Node, Node mem, Node addr, Node data) override { print("{}.write({}, {})", mem, addr, data); }
|
void memory_write(Node, Node mem, Node addr, Node data) override { print("{}.write({}, {})", mem, addr, data); }
|
||||||
};
|
};
|
||||||
|
|
@ -167,14 +169,16 @@ bool equal_def(RTLIL::Const const &a, RTLIL::Const const &b) {
|
||||||
|
|
||||||
struct CxxModule {
|
struct CxxModule {
|
||||||
Functional::IR ir;
|
Functional::IR ir;
|
||||||
|
Design *design;
|
||||||
CxxStruct input_struct, output_struct, state_struct;
|
CxxStruct input_struct, output_struct, state_struct;
|
||||||
std::string module_name;
|
std::string module_name;
|
||||||
|
|
||||||
explicit CxxModule(Module *module) :
|
explicit CxxModule(Module *module) :
|
||||||
ir(Functional::IR::from_module(module)),
|
ir(Functional::IR::from_module(module)),
|
||||||
input_struct("Inputs"),
|
design(module->design),
|
||||||
output_struct("Outputs"),
|
input_struct("Inputs", module->design),
|
||||||
state_struct("State")
|
output_struct("Outputs", module->design),
|
||||||
|
state_struct("State", module->design)
|
||||||
{
|
{
|
||||||
for (auto input : ir.inputs())
|
for (auto input : ir.inputs())
|
||||||
input_struct.insert(input->name, input->sort);
|
input_struct.insert(input->name, input->sort);
|
||||||
|
|
@ -182,7 +186,7 @@ struct CxxModule {
|
||||||
output_struct.insert(output->name, output->sort);
|
output_struct.insert(output->name, output->sort);
|
||||||
for (auto state : ir.states())
|
for (auto state : ir.states())
|
||||||
state_struct.insert(state->name, state->sort);
|
state_struct.insert(state->name, state->sort);
|
||||||
module_name = CxxScope<int>().unique_name(module->name);
|
module_name = CxxScope<int>(module->design).unique_name(module->name.ref());
|
||||||
}
|
}
|
||||||
void write_header(CxxWriter &f) {
|
void write_header(CxxWriter &f) {
|
||||||
f.print("#include \"sim.h\"\n\n");
|
f.print("#include \"sim.h\"\n\n");
|
||||||
|
|
@ -218,7 +222,7 @@ struct CxxModule {
|
||||||
}
|
}
|
||||||
void write_eval_def(CxxWriter &f) {
|
void write_eval_def(CxxWriter &f) {
|
||||||
f.print("void {0}::eval({0}::Inputs const &input, {0}::Outputs &output, {0}::State const ¤t_state, {0}::State &next_state)\n{{\n", module_name);
|
f.print("void {0}::eval({0}::Inputs const &input, {0}::Outputs &output, {0}::State const ¤t_state, {0}::State &next_state)\n{{\n", module_name);
|
||||||
CxxScope<int> locals;
|
CxxScope<int> locals(design);
|
||||||
locals.reserve("input");
|
locals.reserve("input");
|
||||||
locals.reserve("output");
|
locals.reserve("output");
|
||||||
locals.reserve("current_state");
|
locals.reserve("current_state");
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ const char *reserved_keywords[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SmtScope : public Functional::Scope<int> {
|
struct SmtScope : public Functional::Scope<int> {
|
||||||
SmtScope() {
|
SmtScope(Design *design = nullptr) {
|
||||||
|
this->design = design;
|
||||||
for(const char **p = reserved_keywords; *p != nullptr; p++)
|
for(const char **p = reserved_keywords; *p != nullptr; p++)
|
||||||
reserve(*p);
|
reserve(*p);
|
||||||
}
|
}
|
||||||
|
|
@ -72,15 +73,16 @@ class SmtStruct {
|
||||||
SmtSort sort;
|
SmtSort sort;
|
||||||
std::string accessor;
|
std::string accessor;
|
||||||
};
|
};
|
||||||
idict<IdString> field_names;
|
idict<TwineRef> field_names;
|
||||||
vector<Field> fields;
|
vector<Field> fields;
|
||||||
SmtScope &scope;
|
SmtScope &scope;
|
||||||
|
Design *design;
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
SmtStruct(std::string name, SmtScope &scope) : scope(scope), name(name) {}
|
SmtStruct(std::string name, SmtScope &scope, Design *design) : scope(scope), design(design), name(name) {}
|
||||||
void insert(IdString field_name, SmtSort sort) {
|
void insert(TwineRef field_name, SmtSort sort) {
|
||||||
field_names(field_name);
|
field_names(field_name);
|
||||||
auto accessor = scope.unique_name("\\" + name + "_" + design->twines.unescaped_str(field_name));
|
auto accessor = scope.unique_name(design->twines.add("\\" + name + "_" + design->twines.unescaped_str(field_name)));
|
||||||
fields.emplace_back(Field{sort, accessor});
|
fields.emplace_back(Field{sort, accessor});
|
||||||
}
|
}
|
||||||
void write_definition(SExprWriter &w) {
|
void write_definition(SExprWriter &w) {
|
||||||
|
|
@ -99,12 +101,12 @@ public:
|
||||||
w.open(list(name));
|
w.open(list(name));
|
||||||
for(auto field_name : field_names) {
|
for(auto field_name : field_names) {
|
||||||
w << fn(field_name);
|
w << fn(field_name);
|
||||||
w.comment(field_name.unescape(), true);
|
w.comment(design->twines.unescaped_str(field_name), true);
|
||||||
}
|
}
|
||||||
w.close();
|
w.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SExpr access(SExpr record, IdString name) {
|
SExpr access(SExpr record, TwineRef name) {
|
||||||
size_t i = field_names.at(name);
|
size_t i = field_names.at(name);
|
||||||
return list(fields[i].accessor, std::move(record));
|
return list(fields[i].accessor, std::move(record));
|
||||||
}
|
}
|
||||||
|
|
@ -179,8 +181,8 @@ struct SmtPrintVisitor : public Functional::AbstractVisitor<SExpr> {
|
||||||
SExpr memory_read(Node, Node mem, Node addr) override { return list("select", n(mem), n(addr)); }
|
SExpr memory_read(Node, Node mem, Node addr) override { return list("select", n(mem), n(addr)); }
|
||||||
SExpr memory_write(Node, Node mem, Node addr, Node data) override { return list("store", n(mem), n(addr), n(data)); }
|
SExpr memory_write(Node, Node mem, Node addr, Node data) override { return list("store", n(mem), n(addr), n(data)); }
|
||||||
|
|
||||||
SExpr input(Node, IdString name, IdString kind) override { log_assert(kind == TW($input)); return input_struct.access("inputs", name); }
|
SExpr input(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($input)); return input_struct.access("inputs", name); }
|
||||||
SExpr state(Node, IdString name, IdString kind) override { log_assert(kind == TW($state)); return state_struct.access("state", name); }
|
SExpr state(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($state)); return state_struct.access("state", name); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SmtModule {
|
struct SmtModule {
|
||||||
|
|
@ -194,11 +196,11 @@ struct SmtModule {
|
||||||
|
|
||||||
SmtModule(Module *module)
|
SmtModule(Module *module)
|
||||||
: ir(Functional::IR::from_module(module))
|
: ir(Functional::IR::from_module(module))
|
||||||
, scope()
|
, scope(module->design)
|
||||||
, name(scope.unique_name(module->name))
|
, name(scope.unique_name(module->name.ref()))
|
||||||
, input_struct(scope.unique_name(module->name.str() + "_Inputs"), scope)
|
, input_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_Inputs")), scope, module->design)
|
||||||
, output_struct(scope.unique_name(module->name.str() + "_Outputs"), scope)
|
, output_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_Outputs")), scope, module->design)
|
||||||
, state_struct(scope.unique_name(module->name.str() + "_State"), scope)
|
, state_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_State")), scope, module->design)
|
||||||
{
|
{
|
||||||
scope.reserve(name + "-initial");
|
scope.reserve(name + "-initial");
|
||||||
for (auto input : ir.inputs())
|
for (auto input : ir.inputs())
|
||||||
|
|
@ -233,8 +235,8 @@ struct SmtModule {
|
||||||
w.comment(SmtSort(n.sort()).to_sexpr().to_string(), true);
|
w.comment(SmtSort(n.sort()).to_sexpr().to_string(), true);
|
||||||
}
|
}
|
||||||
w.open(list("pair"));
|
w.open(list("pair"));
|
||||||
output_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.output(name).value()); });
|
output_struct.write_value(w, [&](TwineRef name) { return node_to_sexpr(ir.output(name).value()); });
|
||||||
state_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.state(name).next_value()); });
|
state_struct.write_value(w, [&](TwineRef name) { return node_to_sexpr(ir.state(name).next_value()); });
|
||||||
w.pop();
|
w.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ const char *reserved_keywords[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SmtrScope : public Functional::Scope<int> {
|
struct SmtrScope : public Functional::Scope<int> {
|
||||||
SmtrScope() {
|
SmtrScope(Design *design = nullptr) {
|
||||||
|
this->design = design;
|
||||||
for(const char **p = reserved_keywords; *p != nullptr; p++)
|
for(const char **p = reserved_keywords; *p != nullptr; p++)
|
||||||
reserve(*p);
|
reserve(*p);
|
||||||
}
|
}
|
||||||
|
|
@ -73,14 +74,15 @@ class SmtrStruct {
|
||||||
std::string accessor;
|
std::string accessor;
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
idict<IdString> field_names;
|
idict<TwineRef> field_names;
|
||||||
vector<Field> fields;
|
vector<Field> fields;
|
||||||
SmtrScope &global_scope;
|
SmtrScope &global_scope;
|
||||||
SmtrScope local_scope;
|
SmtrScope local_scope;
|
||||||
|
Design *design;
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
SmtrStruct(std::string name, SmtrScope &scope) : global_scope(scope), local_scope(), name(name) {}
|
SmtrStruct(std::string name, SmtrScope &scope, Design *design) : global_scope(scope), local_scope(design), design(design), name(name) {}
|
||||||
void insert(IdString field_name, SmtrSort sort) {
|
void insert(TwineRef field_name, SmtrSort sort) {
|
||||||
field_names(field_name);
|
field_names(field_name);
|
||||||
auto base_name = local_scope.unique_name(field_name);
|
auto base_name = local_scope.unique_name(field_name);
|
||||||
auto accessor = name + "-" + base_name;
|
auto accessor = name + "-" + base_name;
|
||||||
|
|
@ -106,11 +108,11 @@ public:
|
||||||
w.open(list(name));
|
w.open(list(name));
|
||||||
for(auto field_name : field_names) {
|
for(auto field_name : field_names) {
|
||||||
w << fn(field_name);
|
w << fn(field_name);
|
||||||
w.comment(field_name.unescape(), true);
|
w.comment(design->twines.unescaped_str(field_name), true);
|
||||||
}
|
}
|
||||||
w.close();
|
w.close();
|
||||||
}
|
}
|
||||||
SExpr access(SExpr record, IdString name) {
|
SExpr access(SExpr record, TwineRef name) {
|
||||||
size_t i = field_names.at(name);
|
size_t i = field_names.at(name);
|
||||||
return list(fields[i].accessor, std::move(record));
|
return list(fields[i].accessor, std::move(record));
|
||||||
}
|
}
|
||||||
|
|
@ -180,12 +182,13 @@ struct SmtrPrintVisitor : public Functional::AbstractVisitor<SExpr> {
|
||||||
SExpr memory_read(Node, Node mem, Node addr) override { return list("list-ref-bv", n(mem), n(addr)); }
|
SExpr memory_read(Node, Node mem, Node addr) override { return list("list-ref-bv", n(mem), n(addr)); }
|
||||||
SExpr memory_write(Node, Node mem, Node addr, Node data) override { return list("list-set-bv", n(mem), n(addr), n(data)); }
|
SExpr memory_write(Node, Node mem, Node addr, Node data) override { return list("list-set-bv", n(mem), n(addr), n(data)); }
|
||||||
|
|
||||||
SExpr input(Node, IdString name, IdString kind) override { log_assert(kind == TW($input)); return input_struct.access("inputs", name); }
|
SExpr input(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($input)); return input_struct.access("inputs", name); }
|
||||||
SExpr state(Node, IdString name, IdString kind) override { log_assert(kind == TW($state)); return state_struct.access("state", name); }
|
SExpr state(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($state)); return state_struct.access("state", name); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SmtrModule {
|
struct SmtrModule {
|
||||||
Functional::IR ir;
|
Functional::IR ir;
|
||||||
|
Design *design;
|
||||||
SmtrScope scope;
|
SmtrScope scope;
|
||||||
std::string name;
|
std::string name;
|
||||||
bool use_assoc_list_helpers;
|
bool use_assoc_list_helpers;
|
||||||
|
|
@ -197,16 +200,16 @@ struct SmtrModule {
|
||||||
SmtrStruct state_struct;
|
SmtrStruct state_struct;
|
||||||
|
|
||||||
SmtrModule(Module *module, bool assoc_list_helpers)
|
SmtrModule(Module *module, bool assoc_list_helpers)
|
||||||
: ir(Functional::IR::from_module(module)), scope(), name(scope.unique_name(module->name)), use_assoc_list_helpers(assoc_list_helpers),
|
: ir(Functional::IR::from_module(module)), design(module->design), scope(module->design), name(scope.unique_name(module->name.ref())), use_assoc_list_helpers(assoc_list_helpers),
|
||||||
input_struct(scope.unique_name(module->name.str() + "_Inputs"), scope),
|
input_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_Inputs")), scope, module->design),
|
||||||
output_struct(scope.unique_name(module->name.str() + "_Outputs"), scope),
|
output_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_Outputs")), scope, module->design),
|
||||||
state_struct(scope.unique_name(module->name.str() + "_State"), scope)
|
state_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_State")), scope, module->design)
|
||||||
{
|
{
|
||||||
scope.reserve(name + "_initial");
|
scope.reserve(name + "_initial");
|
||||||
if (assoc_list_helpers) {
|
if (assoc_list_helpers) {
|
||||||
input_helper_name = scope.unique_name(module->name.str() + "_inputs_helper");
|
input_helper_name = scope.unique_name(module->design->twines.add(module->name.str() + "_inputs_helper"));
|
||||||
scope.reserve(*input_helper_name);
|
scope.reserve(*input_helper_name);
|
||||||
output_helper_name = scope.unique_name(module->name.str() + "_outputs_helper");
|
output_helper_name = scope.unique_name(module->design->twines.add(module->name.str() + "_outputs_helper"));
|
||||||
scope.reserve(*output_helper_name);
|
scope.reserve(*output_helper_name);
|
||||||
}
|
}
|
||||||
for (auto input : ir.inputs())
|
for (auto input : ir.inputs())
|
||||||
|
|
@ -238,8 +241,8 @@ struct SmtrModule {
|
||||||
w.comment(SmtrSort(n.sort()).to_sexpr().to_string(), true);
|
w.comment(SmtrSort(n.sort()).to_sexpr().to_string(), true);
|
||||||
}
|
}
|
||||||
w.open(list("cons"));
|
w.open(list("cons"));
|
||||||
output_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.output(name).value()); });
|
output_struct.write_value(w, [&](TwineRef name) { return node_to_sexpr(ir.output(name).value()); });
|
||||||
state_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.state(name).next_value()); });
|
state_struct.write_value(w, [&](TwineRef name) { return node_to_sexpr(ir.state(name).next_value()); });
|
||||||
w.pop();
|
w.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,7 +366,7 @@ struct FunctionalSmtrBackend : public Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto module : design->selected_modules()) {
|
for (auto module : design->selected_modules()) {
|
||||||
log("Processing module `%s`.\n", module->name.c_str());
|
log("Processing module `%s`.\n", module->name.str().c_str());
|
||||||
SmtrModule smtr(module, assoc_list_helpers);
|
SmtrModule smtr(module, assoc_list_helpers);
|
||||||
smtr.write(*f);
|
smtr.write(*f);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ struct FunctionalTestGeneric : public Pass
|
||||||
log("Dumping module `%s'.\n", module->name);
|
log("Dumping module `%s'.\n", module->name);
|
||||||
auto fir = Functional::IR::from_module(module);
|
auto fir = Functional::IR::from_module(module);
|
||||||
for(auto node : fir)
|
for(auto node : fir)
|
||||||
std::cout << design->twines.unescaped_str(node.name()) << " = " << node.to_string([](auto n) { return design->twines.unescaped_str(n.name()); }) << "\n";
|
std::cout << design->twines.unescaped_str(node.name()) << " = " << node.to_string([](auto n) { return n.design->twines.unescaped_str(n.name()); }) << "\n";
|
||||||
for(auto output : fir.all_outputs())
|
for(auto output : fir.all_outputs())
|
||||||
std::cout << design->twines.unescaped_str(output->kind) << " " << design->twines.unescaped_str(output->name) << " = " << design->twines.unescaped_str(output->value().name()) << "\n";
|
std::cout << design->twines.unescaped_str(output->kind) << " " << design->twines.unescaped_str(output->name) << " = " << design->twines.unescaped_str(output->value().name()) << "\n";
|
||||||
for(auto state : fir.all_states())
|
for(auto state : fir.all_states())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue