From d8e09f4e0c7547110129101beeb593a60945f7db Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 24 Jun 2026 11:53:14 +0200 Subject: [PATCH] functinoal: twines --- backends/functional/cxx.cc | 30 ++++++++++++---------- backends/functional/smtlib.cc | 34 ++++++++++++------------ backends/functional/smtlib_rosette.cc | 37 +++++++++++++++------------ backends/functional/test_generic.cc | 2 +- 4 files changed, 56 insertions(+), 47 deletions(-) diff --git a/backends/functional/cxx.cc b/backends/functional/cxx.cc index 40d0e6e8e..7c81ba652 100644 --- a/backends/functional/cxx.cc +++ b/backends/functional/cxx.cc @@ -44,7 +44,8 @@ const char *reserved_keywords[] = { }; template struct CxxScope : public Functional::Scope { - CxxScope() { + CxxScope(Design *design = nullptr) { + this->design = design; for(const char **p = reserved_keywords; *p != nullptr; p++) this->reserve(*p); } @@ -71,14 +72,15 @@ using CxxWriter = Functional::Writer; struct CxxStruct { std::string name; - dict types; - CxxScope scope; - CxxStruct(std::string name) : name(name) + dict types; + CxxScope scope; + Design *design; + CxxStruct(std::string name, Design *design) : name(name), scope(design), design(design) { scope.reserve("fn"); scope.reserve("visit"); } - void insert(IdString name, CxxType type) { + void insert(TwineRef name, CxxType type) { scope(name, name); types.insert({name, type}); } @@ -94,7 +96,7 @@ struct CxxStruct { f.print("\t\t}}\n"); f.print("\t}};\n\n"); }; - std::string operator[](IdString field) { + std::string operator[](TwineRef field) { return scope(field, field); } }; @@ -151,8 +153,8 @@ template struct CxxPrintVisitor : public Functional::Abstract 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 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 state(Node, IdString name, IdString kind) override { log_assert(kind == TW($state)); print("current_state.{}", state_struct[name]); } + void input(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($input)); print("input.{}", input_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_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 { Functional::IR ir; + Design *design; CxxStruct input_struct, output_struct, state_struct; std::string module_name; explicit CxxModule(Module *module) : ir(Functional::IR::from_module(module)), - input_struct("Inputs"), - output_struct("Outputs"), - state_struct("State") + design(module->design), + input_struct("Inputs", module->design), + output_struct("Outputs", module->design), + state_struct("State", module->design) { for (auto input : ir.inputs()) input_struct.insert(input->name, input->sort); @@ -182,7 +186,7 @@ struct CxxModule { output_struct.insert(output->name, output->sort); for (auto state : ir.states()) state_struct.insert(state->name, state->sort); - module_name = CxxScope().unique_name(module->name); + module_name = CxxScope(module->design).unique_name(module->name.ref()); } void write_header(CxxWriter &f) { f.print("#include \"sim.h\"\n\n"); @@ -218,7 +222,7 @@ struct CxxModule { } 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); - CxxScope locals; + CxxScope locals(design); locals.reserve("input"); locals.reserve("output"); locals.reserve("current_state"); diff --git a/backends/functional/smtlib.cc b/backends/functional/smtlib.cc index 00555bc6c..aac145048 100644 --- a/backends/functional/smtlib.cc +++ b/backends/functional/smtlib.cc @@ -44,7 +44,8 @@ const char *reserved_keywords[] = { }; struct SmtScope : public Functional::Scope { - SmtScope() { + SmtScope(Design *design = nullptr) { + this->design = design; for(const char **p = reserved_keywords; *p != nullptr; p++) reserve(*p); } @@ -72,15 +73,16 @@ class SmtStruct { SmtSort sort; std::string accessor; }; - idict field_names; + idict field_names; vector fields; SmtScope &scope; + Design *design; public: std::string name; - SmtStruct(std::string name, SmtScope &scope) : scope(scope), name(name) {} - void insert(IdString field_name, SmtSort sort) { + SmtStruct(std::string name, SmtScope &scope, Design *design) : scope(scope), design(design), name(name) {} + void insert(TwineRef field_name, SmtSort sort) { 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}); } void write_definition(SExprWriter &w) { @@ -99,12 +101,12 @@ public: w.open(list(name)); for(auto field_name : field_names) { w << fn(field_name); - w.comment(field_name.unescape(), true); + w.comment(design->twines.unescaped_str(field_name), true); } w.close(); } } - SExpr access(SExpr record, IdString name) { + SExpr access(SExpr record, TwineRef name) { size_t i = field_names.at(name); return list(fields[i].accessor, std::move(record)); } @@ -179,8 +181,8 @@ struct SmtPrintVisitor : public Functional::AbstractVisitor { 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 input(Node, IdString name, IdString 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 input(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($input)); return input_struct.access("inputs", name); } + SExpr state(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($state)); return state_struct.access("state", name); } }; struct SmtModule { @@ -194,11 +196,11 @@ struct SmtModule { SmtModule(Module *module) : ir(Functional::IR::from_module(module)) - , scope() - , name(scope.unique_name(module->name)) - , input_struct(scope.unique_name(module->name.str() + "_Inputs"), scope) - , output_struct(scope.unique_name(module->name.str() + "_Outputs"), scope) - , state_struct(scope.unique_name(module->name.str() + "_State"), scope) + , scope(module->design) + , name(scope.unique_name(module->name.ref())) + , input_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_Inputs")), scope, module->design) + , output_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_Outputs")), scope, module->design) + , state_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_State")), scope, module->design) { scope.reserve(name + "-initial"); for (auto input : ir.inputs()) @@ -233,8 +235,8 @@ struct SmtModule { w.comment(SmtSort(n.sort()).to_sexpr().to_string(), true); } w.open(list("pair")); - output_struct.write_value(w, [&](IdString 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()); }); + output_struct.write_value(w, [&](TwineRef name) { return node_to_sexpr(ir.output(name).value()); }); + state_struct.write_value(w, [&](TwineRef name) { return node_to_sexpr(ir.state(name).next_value()); }); w.pop(); } diff --git a/backends/functional/smtlib_rosette.cc b/backends/functional/smtlib_rosette.cc index 7b6275d48..181c344d1 100644 --- a/backends/functional/smtlib_rosette.cc +++ b/backends/functional/smtlib_rosette.cc @@ -44,7 +44,8 @@ const char *reserved_keywords[] = { }; struct SmtrScope : public Functional::Scope { - SmtrScope() { + SmtrScope(Design *design = nullptr) { + this->design = design; for(const char **p = reserved_keywords; *p != nullptr; p++) reserve(*p); } @@ -73,14 +74,15 @@ class SmtrStruct { std::string accessor; std::string name; }; - idict field_names; + idict field_names; vector fields; SmtrScope &global_scope; SmtrScope local_scope; + Design *design; public: std::string name; - SmtrStruct(std::string name, SmtrScope &scope) : global_scope(scope), local_scope(), name(name) {} - void insert(IdString field_name, SmtrSort sort) { + SmtrStruct(std::string name, SmtrScope &scope, Design *design) : global_scope(scope), local_scope(design), design(design), name(name) {} + void insert(TwineRef field_name, SmtrSort sort) { field_names(field_name); auto base_name = local_scope.unique_name(field_name); auto accessor = name + "-" + base_name; @@ -106,11 +108,11 @@ public: w.open(list(name)); for(auto field_name : field_names) { w << fn(field_name); - w.comment(field_name.unescape(), true); + w.comment(design->twines.unescaped_str(field_name), true); } w.close(); } - SExpr access(SExpr record, IdString name) { + SExpr access(SExpr record, TwineRef name) { size_t i = field_names.at(name); return list(fields[i].accessor, std::move(record)); } @@ -180,12 +182,13 @@ struct SmtrPrintVisitor : public Functional::AbstractVisitor { 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 input(Node, IdString name, IdString 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 input(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($input)); return input_struct.access("inputs", name); } + SExpr state(Node, TwineRef name, TwineRef kind) override { log_assert(kind == TW($state)); return state_struct.access("state", name); } }; struct SmtrModule { Functional::IR ir; + Design *design; SmtrScope scope; std::string name; bool use_assoc_list_helpers; @@ -197,16 +200,16 @@ struct SmtrModule { SmtrStruct state_struct; 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), - input_struct(scope.unique_name(module->name.str() + "_Inputs"), scope), - output_struct(scope.unique_name(module->name.str() + "_Outputs"), scope), - state_struct(scope.unique_name(module->name.str() + "_State"), scope) + : 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->design->twines.add(module->name.str() + "_Inputs")), scope, module->design), + output_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_Outputs")), scope, module->design), + state_struct(scope.unique_name(module->design->twines.add(module->name.str() + "_State")), scope, module->design) { scope.reserve(name + "_initial"); 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); - 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); } for (auto input : ir.inputs()) @@ -238,8 +241,8 @@ struct SmtrModule { w.comment(SmtrSort(n.sort()).to_sexpr().to_string(), true); } w.open(list("cons")); - output_struct.write_value(w, [&](IdString 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()); }); + output_struct.write_value(w, [&](TwineRef name) { return node_to_sexpr(ir.output(name).value()); }); + state_struct.write_value(w, [&](TwineRef name) { return node_to_sexpr(ir.state(name).next_value()); }); w.pop(); } @@ -363,7 +366,7 @@ struct FunctionalSmtrBackend : public Backend { } 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); smtr.write(*f); } diff --git a/backends/functional/test_generic.cc b/backends/functional/test_generic.cc index 0c6336b92..c7cff3654 100644 --- a/backends/functional/test_generic.cc +++ b/backends/functional/test_generic.cc @@ -146,7 +146,7 @@ struct FunctionalTestGeneric : public Pass log("Dumping module `%s'.\n", module->name); auto fir = Functional::IR::from_module(module); 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()) 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())