Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functional Backend #4536

Merged
merged 93 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
0922142
Add generic topological sort and SCC detection
jix Apr 15, 2024
c73c8a3
kernel/log: Add log_str helper for custom log_* functions/overloads
jix Apr 15, 2024
f24e253
kernel/rtlil: Add `SigBit operator[](int offset)` to `SigChunk`
jix Apr 15, 2024
5657297
drivertools: Utility code for indexing and traversing signal drivers
jix Apr 15, 2024
68c3a47
WIP temporary drivertools example
jix Apr 15, 2024
f29422f
topo_scc: Add sources_first option
jix Apr 11, 2024
d4e3daa
ComputeGraph datatype for the upcoming functional backend
jix Apr 11, 2024
d90268f
fixup! drivertools: Utility code for indexing and traversing signal d…
jix Apr 17, 2024
dd5ec84
fix bugs in drivertools
aiju May 1, 2024
63dea89
add initial version of functional C++ backend
aiju May 1, 2024
7611dda
add initial version of functional smtlib backend
aiju May 23, 2024
720429b
Add test_cell tests for C++ functional backend
RCoeurjoly Jun 12, 2024
76371d1
Change assert to log_assert
RCoeurjoly Jun 12, 2024
7b29d17
add support for memories to c++ and smtlib functional backends
aiju Jun 12, 2024
3552a8a
sim.h cannot use log_assert because does not include yosys headers
RCoeurjoly Jun 12, 2024
dbf2bc3
need unsigned comparison when checking shift widths for overflow in f…
aiju Jun 12, 2024
248d5f7
add support for std::variant to hashlib
aiju Jun 20, 2024
6f9e212
add new generic compute graph and rewrite c++ functional backend to u…
aiju Jun 20, 2024
4e370f4
Initial functional SMT backend using functional IR
RCoeurjoly Jun 21, 2024
54225b5
Add test for SMT backend. Tests if SMT is valid and compares simulati…
RCoeurjoly Jun 21, 2024
c6e1126
Remove unused includes
RCoeurjoly Jun 23, 2024
547c546
Ignore smt2 files, generated by the execution of the tests
RCoeurjoly Jun 24, 2024
71aaa1c
Consolidate tests scripts into one
RCoeurjoly Jun 24, 2024
b98210d
Valid SMT is emitted, improved test script
RCoeurjoly Jun 26, 2024
94ddbc9
Fix reduce_or
RCoeurjoly Jun 26, 2024
4109fce
clang-format smtlib.cc
RCoeurjoly Jun 26, 2024
39bf4f0
Create VCD file from SMT file
RCoeurjoly Jun 26, 2024
eb2bb8c
tidy up generic functional backend, add generic scope class, tidy up …
aiju Jun 27, 2024
21bb1cf
rewrite functional c++ simulation library
aiju Jun 27, 2024
e235fc7
Create std::mt19937 only once
RCoeurjoly Jun 27, 2024
ee6bd59
Removed unnecesary nested_lets variable, use writer.print instead
RCoeurjoly Jun 27, 2024
32cdf25
Use FunctionalTools::Scope instead of replaceCharacters
RCoeurjoly Jun 27, 2024
9700df5
add generic writer class with formatting function to FunctionalTools
aiju Jul 4, 2024
cb5f083
´SMT success only if simulation is equivalent
RCoeurjoly Jul 3, 2024
73ed514
Check that there are not other solutions other than the first given
RCoeurjoly Jul 4, 2024
762f8dd
Add readme explaining how to create test files
RCoeurjoly Jul 4, 2024
50f487e
Added $ff test
RCoeurjoly Jul 4, 2024
1b2986f
add support for $mul, $div, $divfloor, $mod, $modfloor, $pow in funct…
aiju Jul 4, 2024
57af68a
include algorithm, needed for std::reverse
RCoeurjoly Jul 4, 2024
e296b88
Add Makefile helpers for coverage
mmicko Jul 5, 2024
f0f436c
Fix parenthesis for arithmetic_shift_right
RCoeurjoly Jul 5, 2024
5780357
Emit valid SMT for stateful designs, fix some cells
RCoeurjoly Jul 7, 2024
fad76ce
Fix memory leak
RCoeurjoly Jul 7, 2024
7cff8fa
Fix corner case of pos cell with input and output being same width
RCoeurjoly Jul 7, 2024
566e57d
Support $lut cells. Both C++ and SMT tests pass
RCoeurjoly Jul 7, 2024
80582ed
Check the existance of a different set of outputs. No need for (push …
RCoeurjoly Jul 8, 2024
9f660b1
rewrite smtlib pass to use SExpr class
aiju Jul 10, 2024
c659ef2
change smtlib backend to use list() function instead of SExpr{} const…
aiju Jul 10, 2024
00a6575
factor out SExpr/SExprWriter classes out of smtlib backend, and also …
aiju Jul 11, 2024
6e7ae88
fix bugs in smtlib backend
aiju Jul 12, 2024
9ad859f
add bwmux, bweqx, bmux, demux cells
aiju Jul 12, 2024
674e6d2
rewrite functional backend test code in python
aiju Jul 12, 2024
6922633
fix a few bugs in the functional backend and refactor the testing
aiju Jul 16, 2024
55c2c17
document functionalir.h and change visitors to derive from AbstractVi…
aiju Jul 17, 2024
7f8f21b
remove widths parameters from FunctionalIR factory methods and from f…
aiju Jul 17, 2024
c0c90c2
functional backend: require shift width == clog2(operand width)
aiju Jul 17, 2024
13bacc5
eliminate pmux in functional backend
aiju Jul 17, 2024
3cd5f4e
add support for RTLIL cells with multiple outputs to the functional b…
aiju Jul 17, 2024
4722f13
functional backend: reduce $lcu to $alu
aiju Jul 18, 2024
145af6f
fix memory handling in functional backend, add more error messages an…
aiju Jul 18, 2024
6d329e1
functional backend: error out if multiply driven or undriven signals …
aiju Jul 18, 2024
12a31a4
add MemContents class to mem.h
aiju Jul 24, 2024
bdb59ff
add -fst-noinit flag to sim for not initializing the state from the f…
aiju Jul 24, 2024
99effb6
add support for initializing registers and memories to the functional…
aiju Jul 24, 2024
95d28c2
functional backend: make Memory in the C++ simulation library read-on…
aiju Jul 24, 2024
7ac0e92
functional backend: rename get_input and get_current_state to input a…
aiju Jul 25, 2024
8c0f625
functional backend: topological sort starts with the output and next …
aiju Jul 25, 2024
850b3a6
convert class FunctionalIR to a namespace Functional, rename function…
aiju Jul 25, 2024
fbee310
add optional header and hashlib implementation for optional
aiju Jul 25, 2024
8f77494
silence some warnings
aiju Jul 25, 2024
79a1b69
silence some more warnings, undo mistaken addition
aiju Jul 25, 2024
50047d2
functional backend: add different types of input/output/state variables
aiju Aug 6, 2024
831da51
add picorv test to functional backend
aiju Aug 8, 2024
f456761
add sandia copyright notice to the functional backend
aiju Aug 13, 2024
9b5e81b
drivertools: fix C++20 "incomplete type" error by moving constructors…
aiju Aug 22, 2024
761eff5
functional backend: missing includes for stl containers
aiju Aug 22, 2024
459e6b9
add functional ir documentation
aiju Aug 27, 2024
b428bf4
functional backends: identifiers in c++/smtlib may not start with digits
aiju Aug 27, 2024
27efed2
functional backend: more documentation
aiju Aug 28, 2024
4eeb8d3
functional backend: rename "type" to either "kind" or "sort" to make …
aiju Aug 28, 2024
2b8db94
functional backend: add test to verify test_generic
aiju Aug 29, 2024
8b29629
smtr: Fork smtlib for rosette
KrystalDelusion Aug 22, 2024
7fe9157
smtr: Add rkt to functional tests
KrystalDelusion Aug 22, 2024
07b6908
smtr: Use rosette/safe
KrystalDelusion Aug 29, 2024
5a29b3e
smtr: More sanitization
KrystalDelusion Aug 29, 2024
a2abbcb
smtr: Use scope.unique_name
KrystalDelusion Sep 3, 2024
d6c5e13
smtr: Structs have local scope
KrystalDelusion Sep 3, 2024
75ed6d3
fix rst formatting in functional_ir.rst
aiju Sep 3, 2024
7de8be1
functional_ir.rst: fix typo, document SExprWriter::flush
aiju Sep 3, 2024
5a476a8
functional tests: run from make tests but not smtlib/rkt tests
aiju Sep 4, 2024
21494d1
Makefile: Update coverage_functional
KrystalDelusion Sep 4, 2024
fc10a6e
Run functional tests on private runner only
mmicko Sep 6, 2024
0ad2431
Merge pull request #4585 from YosysHQ/functional_tests
mmicko Sep 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test-verific.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
echo "ENABLE_FUNCTIONAL_TESTS := 1" >> Makefile.conf
make -j${{ env.procs }} ENABLE_LTO=1

- name: Install Yosys
Expand Down
19 changes: 18 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ ENABLE_LTO := 0
ENABLE_CCACHE := 0
# sccache is not always a drop-in replacement for ccache in practice
ENABLE_SCCACHE := 0
ENABLE_FUNCTIONAL_TESTS := 0
LINK_CURSES := 0
LINK_TERMCAP := 0
LINK_ABC := 0
Expand Down Expand Up @@ -598,6 +599,7 @@ $(eval $(call add_include_file,kernel/celltypes.h))
$(eval $(call add_include_file,kernel/consteval.h))
$(eval $(call add_include_file,kernel/constids.inc))
$(eval $(call add_include_file,kernel/cost.h))
$(eval $(call add_include_file,kernel/drivertools.h))
$(eval $(call add_include_file,kernel/ff.h))
$(eval $(call add_include_file,kernel/ffinit.h))
$(eval $(call add_include_file,kernel/ffmerge.h))
Expand All @@ -616,6 +618,7 @@ $(eval $(call add_include_file,kernel/register.h))
$(eval $(call add_include_file,kernel/rtlil.h))
$(eval $(call add_include_file,kernel/satgen.h))
$(eval $(call add_include_file,kernel/scopeinfo.h))
$(eval $(call add_include_file,kernel/sexpr.h))
$(eval $(call add_include_file,kernel/sigtools.h))
$(eval $(call add_include_file,kernel/timinginfo.h))
$(eval $(call add_include_file,kernel/utils.h))
Expand All @@ -637,7 +640,8 @@ $(eval $(call add_include_file,backends/rtlil/rtlil_backend.h))

OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o
OBJS += kernel/binding.o
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o kernel/sexpr.o
OBJS += kernel/drivertools.o kernel/functional.o
ifeq ($(ENABLE_ZLIB),1)
OBJS += kernel/fstdata.o
endif
Expand Down Expand Up @@ -888,6 +892,9 @@ endif
+cd tests/xprop && bash run-test.sh $(SEEDOPT)
+cd tests/fmt && bash run-test.sh
+cd tests/cxxrtl && bash run-test.sh
ifeq ($(ENABLE_FUNCTIONAL_TESTS),1)
+cd tests/functional && bash run-test.sh
endif
@echo ""
@echo " Passed \"make test\"."
@echo ""
Expand Down Expand Up @@ -1045,6 +1052,16 @@ coverage:
lcov --capture -d . --no-external -o coverage.info
genhtml coverage.info --output-directory coverage_html

clean_coverage:
find . -name "*.gcda" -type f -delete

FUNC_KERNEL := functional.cc functional.h sexpr.cc sexpr.h compute_graph.h
FUNC_INCLUDES := $(addprefix --include *,functional/* $(FUNC_KERNEL))
coverage_functional:
rm -rf coverage.info coverage_html
lcov --capture -d backends/functional -d kernel $(FUNC_INCLUDES) --no-external -o coverage.info
genhtml coverage.info --output-directory coverage_html

qtcreator:
echo "$(CXXFLAGS)" | grep -o '\-D[^ ]*' | tr ' ' '\n' | sed 's/-D/#define /' | sed 's/=/ /'> qtcreator.config
{ for file in $(basename $(OBJS)); do \
Expand Down
4 changes: 4 additions & 0 deletions backends/functional/Makefile.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
OBJS += backends/functional/cxx.o
OBJS += backends/functional/smtlib.o
OBJS += backends/functional/smtlib_rosette.o
OBJS += backends/functional/test_generic.o
275 changes: 275 additions & 0 deletions backends/functional/cxx.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2024 Emily Schmidt <[email protected]>
* Copyright (C) 2024 National Technology and Engineering Solutions of Sandia, LLC
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/

#include "kernel/yosys.h"
#include "kernel/functional.h"
#include <ctype.h>

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

const char *reserved_keywords[] = {
"alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit",
"atomic_noexcept","auto","bitand","bitor","bool","break","case",
"catch","char","char16_t","char32_t","char8_t","class","co_await",
"co_return","co_yield","compl","concept","const","const_cast","consteval",
"constexpr","constinit","continue","decltype","default","delete",
"do","double","dynamic_cast","else","enum","explicit","export",
"extern","false","float","for","friend","goto","if","inline",
"int","long","mutable","namespace","new","noexcept","not","not_eq",
"nullptr","operator","or","or_eq","private","protected","public",
"reflexpr","register","reinterpret_cast","requires","return","short",
"signed","sizeof","static","static_log_assert","static_cast","struct",
"switch","synchronized","template","this","thread_local","throw",
"true","try","typedef","typeid","typename","union","unsigned",
"using","virtual","void","volatile","wchar_t","while","xor","xor_eq",
nullptr
};

template<typename Id> struct CxxScope : public Functional::Scope<Id> {
CxxScope() {
for(const char **p = reserved_keywords; *p != nullptr; p++)
this->reserve(*p);
}
bool is_character_legal(char c, int index) override {
return isascii(c) && (isalpha(c) || (isdigit(c) && index > 0) || c == '_' || c == '$');
}
};

struct CxxType {
Functional::Sort sort;
CxxType(Functional::Sort sort) : sort(sort) {}
std::string to_string() const {
if(sort.is_memory()) {
return stringf("Memory<%d, %d>", sort.addr_width(), sort.data_width());
} else if(sort.is_signal()) {
return stringf("Signal<%d>", sort.width());
} else {
log_error("unknown sort");
}
}
};

using CxxWriter = Functional::Writer;

struct CxxStruct {
std::string name;
dict<IdString, CxxType> types;
CxxScope<IdString> scope;
CxxStruct(std::string name) : name(name)
{
scope.reserve("fn");
scope.reserve("visit");
}
void insert(IdString name, CxxType type) {
scope(name, name);
types.insert({name, type});
}
void print(CxxWriter &f) {
f.print("\tstruct {} {{\n", name);
for (auto p : types) {
f.print("\t\t{} {};\n", p.second.to_string(), scope(p.first, p.first));
}
f.print("\n\t\ttemplate <typename T> void visit(T &&fn) {{\n");
for (auto p : types) {
f.print("\t\t\tfn(\"{}\", {});\n", RTLIL::unescape_id(p.first), scope(p.first, p.first));
}
f.print("\t\t}}\n");
f.print("\t}};\n\n");
};
std::string operator[](IdString field) {
return scope(field, field);
}
};

std::string cxx_const(RTLIL::Const const &value) {
std::stringstream ss;
ss << "Signal<" << value.size() << ">(" << std::hex << std::showbase;
if(value.size() > 32) ss << "{";
for(int i = 0; i < value.size(); i += 32) {
if(i > 0) ss << ", ";
ss << value.extract(i, 32).as_int();
}
if(value.size() > 32) ss << "}";
ss << ")";
return ss.str();
}

template<class NodePrinter> struct CxxPrintVisitor : public Functional::AbstractVisitor<void> {
using Node = Functional::Node;
CxxWriter &f;
NodePrinter np;
CxxStruct &input_struct;
CxxStruct &state_struct;
CxxPrintVisitor(CxxWriter &f, NodePrinter np, CxxStruct &input_struct, CxxStruct &state_struct) : f(f), np(np), input_struct(input_struct), state_struct(state_struct) { }
template<typename... Args> void print(const char *fmt, Args&&... args) {
f.print_with(np, fmt, std::forward<Args>(args)...);
}
void buf(Node, Node n) override { print("{}", n); }
void slice(Node, Node a, int offset, int out_width) override { print("{0}.slice<{2}>({1})", a, offset, out_width); }
void zero_extend(Node, Node a, int out_width) override { print("{}.zero_extend<{}>()", a, out_width); }
void sign_extend(Node, Node a, int out_width) override { print("{}.sign_extend<{}>()", a, out_width); }
void concat(Node, Node a, Node b) override { print("{}.concat({})", a, b); }
void add(Node, Node a, Node b) override { print("{} + {}", a, b); }
void sub(Node, Node a, Node b) override { print("{} - {}", a, b); }
void mul(Node, Node a, Node b) override { print("{} * {}", a, b); }
void unsigned_div(Node, Node a, Node b) override { print("{} / {}", a, b); }
void unsigned_mod(Node, Node a, Node b) override { print("{} % {}", a, b); }
void bitwise_and(Node, Node a, Node b) override { print("{} & {}", a, b); }
void bitwise_or(Node, Node a, Node b) override { print("{} | {}", a, b); }
void bitwise_xor(Node, Node a, Node b) override { print("{} ^ {}", a, b); }
void bitwise_not(Node, Node a) override { print("~{}", a); }
void unary_minus(Node, Node a) override { print("-{}", a); }
void reduce_and(Node, Node a) override { print("{}.all()", a); }
void reduce_or(Node, Node a) override { print("{}.any()", a); }
void reduce_xor(Node, Node a) override { print("{}.parity()", a); }
void equal(Node, Node a, Node b) override { print("{} == {}", a, b); }
void not_equal(Node, Node a, Node b) override { print("{} != {}", a, b); }
void signed_greater_than(Node, Node a, Node b) override { print("{}.signed_greater_than({})", a, b); }
void signed_greater_equal(Node, Node a, Node b) override { print("{}.signed_greater_equal({})", a, b); }
void unsigned_greater_than(Node, Node a, Node b) override { print("{} > {}", a, b); }
void unsigned_greater_equal(Node, Node a, Node b) override { print("{} >= {}", a, b); }
void logical_shift_left(Node, Node a, Node b) override { print("{} << {}", a, b); }
void logical_shift_right(Node, Node a, Node b) override { print("{} >> {}", 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 constant(Node, RTLIL::Const const & value) override { print("{}", cxx_const(value)); }
void input(Node, IdString name, IdString kind) override { log_assert(kind == ID($input)); print("input.{}", input_struct[name]); }
void state(Node, IdString name, IdString kind) override { log_assert(kind == ID($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); }
};

bool equal_def(RTLIL::Const const &a, RTLIL::Const const &b) {
if(a.size() != b.size()) return false;
for(int i = 0; i < a.size(); i++)
if((a[i] == State::S1) != (b[i] == State::S1))
return false;
return true;
}

struct CxxModule {
Functional::IR ir;
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")
{
for (auto input : ir.inputs())
input_struct.insert(input->name, input->sort);
for (auto output : ir.outputs())
output_struct.insert(output->name, output->sort);
for (auto state : ir.states())
state_struct.insert(state->name, state->sort);
module_name = CxxScope<int>().unique_name(module->name);
}
void write_header(CxxWriter &f) {
f.print("#include \"sim.h\"\n\n");
}
void write_struct_def(CxxWriter &f) {
f.print("struct {} {{\n", module_name);
input_struct.print(f);
output_struct.print(f);
state_struct.print(f);
f.print("\tstatic void eval(Inputs const &, Outputs &, State const &, State &);\n");
f.print("\tstatic void initialize(State &);\n");
f.print("}};\n\n");
}
void write_initial_def(CxxWriter &f) {
f.print("void {0}::initialize({0}::State &state)\n{{\n", module_name);
for (auto state : ir.states()) {
if (state->sort.is_signal())
f.print("\tstate.{} = {};\n", state_struct[state->name], cxx_const(state->initial_value_signal()));
else if (state->sort.is_memory()) {
f.print("\t{{\n");
f.print("\t\tstd::array<Signal<{}>, {}> mem;\n", state->sort.data_width(), 1<<state->sort.addr_width());
const auto &contents = state->initial_value_memory();
f.print("\t\tmem.fill({});\n", cxx_const(contents.default_value()));
for(auto range : contents)
for(auto addr = range.base(); addr < range.limit(); addr++)
if(!equal_def(range[addr], contents.default_value()))
f.print("\t\tmem[{}] = {};\n", addr, cxx_const(range[addr]));
f.print("\t\tstate.{} = mem;\n", state_struct[state->name]);
f.print("\t}}\n");
}
}
f.print("}}\n\n");
}
void write_eval_def(CxxWriter &f) {
f.print("void {0}::eval({0}::Inputs const &input, {0}::Outputs &output, {0}::State const &current_state, {0}::State &next_state)\n{{\n", module_name);
CxxScope<int> locals;
locals.reserve("input");
locals.reserve("output");
locals.reserve("current_state");
locals.reserve("next_state");
auto node_name = [&](Functional::Node n) { return locals(n.id(), n.name()); };
CxxPrintVisitor printVisitor(f, node_name, input_struct, state_struct);
for (auto node : ir) {
f.print("\t{} {} = ", CxxType(node.sort()).to_string(), node_name(node));
node.visit(printVisitor);
f.print(";\n");
}
for (auto state : ir.states())
f.print("\tnext_state.{} = {};\n", state_struct[state->name], node_name(state->next_value()));
for (auto output : ir.outputs())
f.print("\toutput.{} = {};\n", output_struct[output->name], node_name(output->value()));
f.print("}}\n\n");
}
};

struct FunctionalCxxBackend : public Backend
{
FunctionalCxxBackend() : Backend("functional_cxx", "convert design to C++ using the functional backend") {}

void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
}

void printCxx(std::ostream &stream, std::string, Module *module)
{
CxxWriter f(stream);
CxxModule mod(module);
mod.write_header(f);
mod.write_struct_def(f);
mod.write_eval_def(f);
mod.write_initial_def(f);
}

void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing Functional C++ backend.\n");

size_t argidx = 1;
extra_args(f, filename, args, argidx, design);

for (auto module : design->selected_modules()) {
log("Dumping module `%s'.\n", module->name.c_str());
printCxx(*f, filename, module);
}
}
} FunctionalCxxBackend;

PRIVATE_NAMESPACE_END
Loading