mirror of
https://github.com/YosysHQ/yosys
synced 2025-07-24 05:08:56 +00:00
add support for initializing registers and memories to the functional backend
This commit is contained in:
parent
bdb59ffc8e
commit
99effb6789
10 changed files with 418 additions and 282 deletions
|
@ -69,35 +69,48 @@ struct CxxType {
|
|||
using CxxWriter = FunctionalTools::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 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 FunctionalIR::AbstractVisitor<void> {
|
||||
using Node = FunctionalIR::Node;
|
||||
CxxWriter &f;
|
||||
|
@ -136,20 +149,7 @@ template<class NodePrinter> struct CxxPrintVisitor : public FunctionalIR::Abstra
|
|||
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 value) override {
|
||||
std::stringstream ss;
|
||||
bool multiple = value.size() > 32;
|
||||
ss << "Signal<" << value.size() << ">(" << std::hex << std::showbase;
|
||||
if(multiple) ss << "{";
|
||||
while(value.size() > 32) {
|
||||
ss << value.as_int() << ", ";
|
||||
value = value.extract(32, value.size() - 32);
|
||||
}
|
||||
ss << value.as_int();
|
||||
if(multiple) ss << "}";
|
||||
ss << ")";
|
||||
print("{}", ss.str());
|
||||
}
|
||||
void constant(Node, RTLIL::Const const & value) override { print("{}", cxx_const(value)); }
|
||||
void input(Node, IdString name) override { print("input.{}", input_struct[name]); }
|
||||
void state(Node, IdString name) override { print("current_state.{}", state_struct[name]); }
|
||||
void memory_read(Node, Node mem, Node addr) override { print("{}.read({})", mem, addr); }
|
||||
|
@ -184,8 +184,24 @@ struct CxxModule {
|
|||
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 [name, sort] : ir.state()) {
|
||||
if (sort.is_signal())
|
||||
f.print("\tstate.{} = {};\n", state_struct[name], cxx_const(ir.get_initial_state_signal(name)));
|
||||
else if (sort.is_memory()) {
|
||||
const auto &contents = ir.get_initial_state_memory(name);
|
||||
f.print("\tstate.{}.fill({});\n", state_struct[name], cxx_const(contents.default_value()));
|
||||
for(auto range : contents)
|
||||
for(auto addr = range.base(); addr < range.limit(); addr++)
|
||||
f.print("\tstate.{}[{}] = {};\n", state_struct[name], addr, cxx_const(range[addr]));
|
||||
}
|
||||
}
|
||||
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 ¤t_state, {0}::State &next_state)\n{{\n", module_name);
|
||||
CxxScope<int> locals;
|
||||
|
@ -204,7 +220,7 @@ struct CxxModule {
|
|||
f.print("\tnext_state.{} = {};\n", state_struct[name], node_name(ir.get_state_next_node(name)));
|
||||
for (auto [name, sort] : ir.outputs())
|
||||
f.print("\toutput.{} = {};\n", output_struct[name], node_name(ir.get_output_node(name)));
|
||||
f.print("}}\n");
|
||||
f.print("}}\n\n");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -225,6 +241,7 @@ struct FunctionalCxxBackend : public Backend
|
|||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue