3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-12-14 15:46:25 +00:00

Merge remote-tracking branch 'origin/main' into gussmith23-rosette-backend-updates

This commit is contained in:
Gus Smith 2025-11-29 14:20:36 -08:00
commit 6fe35fa46c
694 changed files with 33466 additions and 17901 deletions

View file

@ -268,7 +268,7 @@ struct FunctionalCxxBackend : public Backend
extra_args(f, filename, args, argidx, design);
for (auto module : design->selected_modules()) {
log("Dumping module `%s'.\n", module->name.c_str());
log("Dumping module `%s'.\n", module->name);
printCxx(*f, filename, module);
}
}

View file

@ -285,7 +285,7 @@ struct FunctionalSmtBackend : public Backend {
extra_args(f, filename, args, argidx, design);
for (auto module : design->selected_modules()) {
log("Processing module `%s`.\n", module->name.c_str());
log("Processing module `%s`.\n", module->name);
SmtModule smt(module);
smt.write(*f);
}

View file

@ -19,8 +19,8 @@
*/
#include "kernel/functional.h"
#include "kernel/yosys.h"
#include "kernel/sexpr.h"
#include "kernel/yosys.h"
#include <ctype.h>
USING_YOSYS_NAMESPACE
@ -29,26 +29,24 @@ PRIVATE_NAMESPACE_BEGIN
using SExprUtil::list;
const char *reserved_keywords[] = {
// reserved keywords from the racket spec
"struct", "lambda", "values", "extract", "concat", "bv", "let", "define", "cons", "list", "read", "write",
"stream", "error", "raise", "exit", "for", "begin", "when", "unless", "module", "require", "provide", "apply",
"if", "cond", "even", "odd", "any", "and", "or", "match", "command-line", "ffi-lib", "thread", "kill", "sync",
"future", "touch", "subprocess", "make-custodian", "custodian-shutdown-all", "current-custodian", "make", "tcp",
"connect", "prepare", "malloc", "free", "_fun", "_cprocedure", "build", "path", "file", "peek", "bytes",
"flush", "with", "lexer", "parser", "syntax", "interface", "send", "make-object", "new", "instantiate",
"define-generics", "set",
// reserved keywords from the racket spec
"struct", "lambda", "values", "extract", "concat", "bv", "let", "define", "cons", "list", "read", "write", "stream", "error", "raise", "exit",
"for", "begin", "when", "unless", "module", "require", "provide", "apply", "if", "cond", "even", "odd", "any", "and", "or", "match", "command-line",
"ffi-lib", "thread", "kill", "sync", "future", "touch", "subprocess", "make-custodian", "custodian-shutdown-all", "current-custodian", "make",
"tcp", "connect", "prepare", "malloc", "free", "_fun", "_cprocedure", "build", "path", "file", "peek", "bytes", "flush", "with", "lexer", "parser",
"syntax", "interface", "send", "make-object", "new", "instantiate", "define-generics", "set",
// reserved for our own purposes
"inputs", "state", "name",
nullptr
};
// reserved for our own purposes
"inputs", "state", "name", nullptr};
struct SmtrScope : public Functional::Scope<int> {
SmtrScope() {
for(const char **p = reserved_keywords; *p != nullptr; p++)
SmtrScope()
{
for (const char **p = reserved_keywords; *p != nullptr; p++)
reserve(*p);
}
bool is_character_legal(char c, int index) override {
bool is_character_legal(char c, int index) override
{
return isascii(c) && (isalpha(c) || (isdigit(c) && index > 0) || strchr("@$%^&_+=.", c));
}
};
@ -56,10 +54,11 @@ struct SmtrScope : public Functional::Scope<int> {
struct SmtrSort {
Functional::Sort sort;
SmtrSort(Functional::Sort sort) : sort(sort) {}
SExpr to_sexpr() const {
if(sort.is_memory()) {
SExpr to_sexpr() const
{
if (sort.is_memory()) {
return list("list", list("bitvector", sort.addr_width()), list("bitvector", sort.data_width()));
} else if(sort.is_signal()) {
} else if (sort.is_signal()) {
return list("bitvector", sort.width());
} else {
log_error("unknown sort");
@ -67,7 +66,8 @@ struct SmtrSort {
}
};
class SmtrStruct {
class SmtrStruct
{
struct Field {
SmtrSort sort;
std::string accessor;
@ -77,19 +77,22 @@ class SmtrStruct {
vector<Field> fields;
SmtrScope &global_scope;
SmtrScope local_scope;
public:
public:
std::string name;
SmtrStruct(std::string name, SmtrScope &scope) : global_scope(scope), local_scope(), name(name) {}
void insert(IdString field_name, SmtrSort sort) {
void insert(IdString field_name, SmtrSort sort)
{
field_names(field_name);
auto base_name = local_scope.unique_name(field_name);
auto accessor = name + "-" + base_name;
global_scope.reserve(accessor);
fields.emplace_back(Field{sort, accessor, base_name});
}
void write_definition(SExprWriter &w) {
void write_definition(SExprWriter &w)
{
vector<SExpr> field_list;
for(const auto &field : fields) {
for (const auto &field : fields) {
field_list.emplace_back(field.name);
}
w.push();
@ -102,23 +105,26 @@ public:
}
w.pop();
}
template<typename Fn> void write_value(SExprWriter &w, Fn fn) {
template <typename Fn> void write_value(SExprWriter &w, Fn fn)
{
w.open(list(name));
for(auto field_name : field_names) {
for (auto field_name : field_names) {
w << fn(field_name);
w.comment(RTLIL::unescape_id(field_name), true);
}
w.close();
}
SExpr access(SExpr record, IdString name) {
SExpr access(SExpr record, IdString name)
{
size_t i = field_names.at(name);
return list(fields[i].accessor, std::move(record));
}
};
std::string smt_const(RTLIL::Const const &c) {
std::string smt_const(RTLIL::Const const &c)
{
std::string s = "#b";
for(int i = c.size(); i-- > 0; )
for (int i = c.size(); i-- > 0;)
s += c[i] == State::S1 ? '1' : '0';
return s;
}
@ -131,15 +137,9 @@ struct SmtrPrintVisitor : public Functional::AbstractVisitor<SExpr> {
SmtrPrintVisitor(SmtrStruct &input_struct, SmtrStruct &state_struct) : input_struct(input_struct), state_struct(state_struct) {}
SExpr from_bool(SExpr &&arg) {
return list("bool->bitvector", std::move(arg));
}
SExpr to_bool(SExpr &&arg) {
return list("bitvector->bool", std::move(arg));
}
SExpr to_list(SExpr &&arg) {
return list("bitvector->bits", std::move(arg));
}
SExpr from_bool(SExpr &&arg) { return list("bool->bitvector", std::move(arg)); }
SExpr to_bool(SExpr &&arg) { return list("bitvector->bool", std::move(arg)); }
SExpr to_list(SExpr &&arg) { return list("bitvector->bits", std::move(arg)); }
SExpr buf(Node, Node a) override { return n(a); }
SExpr slice(Node, Node a, int offset, int out_width) override { return list("extract", offset + out_width - 1, offset, n(a)); }
@ -166,8 +166,9 @@ struct SmtrPrintVisitor : public Functional::AbstractVisitor<SExpr> {
SExpr unsigned_greater_than(Node, Node a, Node b) override { return from_bool(list("bvugt", n(a), n(b))); }
SExpr unsigned_greater_equal(Node, Node a, Node b) override { return from_bool(list("bvuge", n(a), n(b))); }
SExpr extend(SExpr &&a, int in_width, int out_width) {
if(in_width < out_width)
SExpr extend(SExpr &&a, int in_width, int out_width)
{
if (in_width < out_width)
return list("zero-extend", std::move(a), list("bitvector", out_width));
else
return std::move(a);
@ -176,12 +177,20 @@ struct SmtrPrintVisitor : public Functional::AbstractVisitor<SExpr> {
SExpr logical_shift_right(Node, Node a, Node b) override { return list("bvlshr", n(a), extend(n(b), b.width(), a.width())); }
SExpr arithmetic_shift_right(Node, Node a, Node b) override { return list("bvashr", n(a), extend(n(b), b.width(), a.width())); }
SExpr mux(Node, Node a, Node b, Node s) override { return list("if", to_bool(n(s)), n(b), n(a)); }
SExpr constant(Node, RTLIL::Const const& value) override { return list("bv", smt_const(value), value.size()); }
SExpr constant(Node, RTLIL::Const const &value) override { return list("bv", smt_const(value), value.size()); }
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 == ID($input)); return input_struct.access("inputs", name); }
SExpr state(Node, IdString name, IdString kind) override { log_assert(kind == ID($state)); return state_struct.access("state", name); }
SExpr input(Node, IdString name, IdString kind) override
{
log_assert(kind == ID($input));
return input_struct.access("inputs", name);
}
SExpr state(Node, IdString name, IdString kind) override
{
log_assert(kind == ID($state));
return state_struct.access("state", name);
}
};
struct SmtrModule {
@ -196,12 +205,10 @@ 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))
, 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)), 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.reserve(name + "_initial");
if (assoc_list_helpers) {
@ -222,19 +229,17 @@ struct SmtrModule {
{
w.push();
w.open(list("define", list(name, "inputs", "state")));
auto inlined = [&](Functional::Node n) {
return n.fn() == Functional::Fn::constant;
};
auto inlined = [&](Functional::Node n) { return n.fn() == Functional::Fn::constant; };
SmtrPrintVisitor visitor(input_struct, state_struct);
auto node_to_sexpr = [&](Functional::Node n) -> SExpr {
if(inlined(n))
if (inlined(n))
return n.visit(visitor);
else
return scope(n.id(), n.name());
};
visitor.n = node_to_sexpr;
for(auto n : ir)
if(!inlined(n)) {
for (auto n : ir)
if (!inlined(n)) {
w.open(list("let", list(list(node_to_sexpr(n), n.visit(visitor)))), false);
w.comment(SmtrSort(n.sort()).to_sexpr().to_string(), true);
}
@ -256,7 +261,7 @@ struct SmtrModule {
else if (state->sort.is_memory()) {
const auto &contents = state->initial_value_memory();
w.open(list("list"));
for(int i = 0; i < 1<<state->sort.addr_width(); i++) {
for (int i = 0; i < 1 << state->sort.addr_width(); i++) {
w << list("bv", smt_const(contents[i]), state->sort.data_width());
}
w.close();
@ -303,7 +308,7 @@ struct SmtrModule {
}
void write(std::ostream &out)
{
{
SExprWriter w(out);
input_struct.write_definition(w);
@ -324,8 +329,9 @@ struct SmtrModule {
struct FunctionalSmtrBackend : public Backend {
FunctionalSmtrBackend() : Backend("functional_rosette", "Generate Rosette compatible Racket from Functional IR") {}
void help() override {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_functional_rosette [options] [filename]\n");
log("\n");
@ -347,8 +353,7 @@ struct FunctionalSmtrBackend : public Backend {
log_header(design, "Executing Functional Rosette Backend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-provides")
provides = true;
else if (args[argidx] == "-assoc-list-helpers")

View file

@ -105,7 +105,7 @@ struct MemContentsTest {
RTLIL::Const values;
for(addr_t addr = low; addr <= high; addr++) {
RTLIL::Const word(data_dist(rnd), data_width);
values.bits().insert(values.bits().end(), word.begin(), word.end());
values.append(word);
}
insert_concatenated(low, values);
}
@ -116,7 +116,9 @@ struct MemContentsTest {
struct FunctionalTestGeneric : public Pass
{
FunctionalTestGeneric() : Pass("test_generic", "test the generic compute graph") {}
FunctionalTestGeneric() : Pass("test_generic", "test the generic compute graph") {
internal();
}
void help() override
{
@ -141,7 +143,7 @@ struct FunctionalTestGeneric : public Pass
*/
for (auto module : design->selected_modules()) {
log("Dumping module `%s'.\n", module->name.c_str());
log("Dumping module `%s'.\n", module->name);
auto fir = Functional::IR::from_module(module);
for(auto node : fir)
std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n";