diff --git a/backends/functional/cxx.cc b/backends/functional/cxx.cc index de7737a42..b8b25df8b 100644 --- a/backends/functional/cxx.cc +++ b/backends/functional/cxx.cc @@ -151,8 +151,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 type) override { log_assert(type == ID($input)); print("input.{}", input_struct[name]); } - void state(Node, IdString name, IdString type) override { log_assert(type == ID($state)); print("current_state.{}", state_struct[name]); } + 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); } }; diff --git a/backends/functional/smtlib.cc b/backends/functional/smtlib.cc index ae6ae40ca..3eacf407c 100644 --- a/backends/functional/smtlib.cc +++ b/backends/functional/smtlib.cc @@ -179,8 +179,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 type) override { log_assert(type == ID($input)); return input_struct.access("inputs", name); } - SExpr state(Node, IdString name, IdString type) override { log_assert(type == 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 SmtModule { diff --git a/backends/functional/test_generic.cc b/backends/functional/test_generic.cc index aab2260f1..10a7a50f0 100644 --- a/backends/functional/test_generic.cc +++ b/backends/functional/test_generic.cc @@ -144,9 +144,9 @@ struct FunctionalTestGeneric : public Pass for(auto node : fir) std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n"; for(auto output : fir.all_outputs()) - std::cout << RTLIL::unescape_id(output->type) << " " << RTLIL::unescape_id(output->name) << " = " << RTLIL::unescape_id(output->value().name()) << "\n"; + std::cout << RTLIL::unescape_id(output->kind) << " " << RTLIL::unescape_id(output->name) << " = " << RTLIL::unescape_id(output->value().name()) << "\n"; for(auto state : fir.all_states()) - std::cout << RTLIL::unescape_id(state->type) << " " << RTLIL::unescape_id(state->name) << " = " << RTLIL::unescape_id(state->next_value().name()) << "\n"; + std::cout << RTLIL::unescape_id(state->kind) << " " << RTLIL::unescape_id(state->name) << " = " << RTLIL::unescape_id(state->next_value().name()) << "\n"; } } } FunctionalCxxBackend; diff --git a/docs/source/yosys_internals/extending_yosys/functional_ir.rst b/docs/source/yosys_internals/extending_yosys/functional_ir.rst index 887d44a6e..38d000556 100644 --- a/docs/source/yosys_internals/extending_yosys/functional_ir.rst +++ b/docs/source/yosys_internals/extending_yosys/functional_ir.rst @@ -26,11 +26,11 @@ The `Functional::IR` class supports the syntax `for(auto node : ir)` to iterate `Functional::IR` also keeps track of inputs, outputs and states. By a "state" we mean a pair of a "current state" input and a "next state" output. One such pair is created for every register and for every memory. -Every input, output and state has a name (equal to their name in RTLIL), a sort and a "type". -The "type" field usually remains as the default value `$input`, `$output` or `$state`, however some RTLIL cells such as `$assert` or `$anyseq` generate auxiliary inputs/outputs/states that are given a different type to distinguish them from ordinary RTLIL inputs/outputs/states. -- To access an individual input/output/state, use `ir.input(name, type)`, `ir.output(name, type)` or `ir.state(name, type)`. `type` defaults to the default type. -- To iterate over all inputs/outputs/states of a certain "type", methods `ir.inputs`, `ir.outputs`, `ir.states` are provided. Their argument defaults to the default types mentioned. -- To iterate over inputs/outputs/states of any "type", use `ir.all_inputs`, `ir.all_outputs` and `ir.all_states`. +Every input, output and state has a name (equal to their name in RTLIL), a sort and a kind. +The kind field usually remains as the default value `$input`, `$output` or `$state`, however some RTLIL cells such as `$assert` or `$anyseq` generate auxiliary inputs/outputs/states that are given a different kind to distinguish them from ordinary RTLIL inputs/outputs/states. +- To access an individual input/output/state, use `ir.input(name, kind)`, `ir.output(name, kind)` or `ir.state(name, kind)`. `kind` defaults to the default kind. +- To iterate over all inputs/outputs/states of a certain kind, methods `ir.inputs`, `ir.outputs`, `ir.states` are provided. Their argument defaults to the default kinds mentioned. +- To iterate over inputs/outputs/states of any kind, use `ir.all_inputs`, `ir.all_outputs` and `ir.all_states`. - Outputs have a node that indicate the value of the output, this can be retrieved via `output.value()`. - States have a node that indicate the next value of the state, this can be retrieved via `state.next_value()`. They also have an initial value that is accessed as either `state.initial_value_signal()` or `state.initial_value_memory()`, depending on their sort. diff --git a/kernel/functional.cc b/kernel/functional.cc index 11f030eae..c270a2bb6 100644 --- a/kernel/functional.cc +++ b/kernel/functional.cc @@ -67,26 +67,26 @@ const char *fn_to_string(Fn fn) { log_error("fn_to_string: unknown Functional::Fn value %d", (int)fn); } -vector IR::inputs(IdString type) const { +vector IR::inputs(IdString kind) const { vector ret; for (const auto &[name, input] : _inputs) - if(input.type == type) + if(input.kind == kind) ret.push_back(&input); return ret; } -vector IR::outputs(IdString type) const { +vector IR::outputs(IdString kind) const { vector ret; for (const auto &[name, output] : _outputs) - if(output.type == type) + if(output.kind == kind) ret.push_back(&output); return ret; } -vector IR::states(IdString type) const { +vector IR::states(IdString kind) const { vector ret; for (const auto &[name, state] : _states) - if(state.type == type) + if(state.kind == kind) ret.push_back(&state); return ret; } @@ -120,8 +120,8 @@ struct PrintVisitor : DefaultVisitor { std::string zero_extend(Node, Node a, int out_width) override { return "zero_extend(" + np(a) + ", " + std::to_string(out_width) + ")"; } std::string sign_extend(Node, Node a, int out_width) override { return "sign_extend(" + np(a) + ", " + std::to_string(out_width) + ")"; } std::string constant(Node, RTLIL::Const const& value) override { return "constant(" + value.as_string() + ")"; } - std::string input(Node, IdString name, IdString type) override { return "input(" + name.str() + ", " + type.str() + ")"; } - std::string state(Node, IdString name, IdString type) override { return "state(" + name.str() + ", " + type.str() + ")"; } + std::string input(Node, IdString name, IdString kind) override { return "input(" + name.str() + ", " + kind.str() + ")"; } + std::string state(Node, IdString name, IdString kind) override { return "state(" + name.str() + ", " + kind.str() + ")"; } std::string default_handler(Node self) override { std::string ret = fn_to_string(self.fn()); ret += "("; diff --git a/kernel/functional.h b/kernel/functional.h index 2afdd7fc3..f1fb2767f 100644 --- a/kernel/functional.h +++ b/kernel/functional.h @@ -34,7 +34,7 @@ namespace Functional { // each function is documented with a short pseudocode declaration or definition // standard C/Verilog operators are used to describe the result // - // the types used in this are: + // the sorts used in this are: // - bit[N]: a bitvector of N bits // bit[N] can be indicated as signed or unsigned. this is not tracked by the functional backend // but is meant to indicate how the value is interpreted @@ -43,12 +43,12 @@ namespace Functional { // - int: C++ int // - Const[N]: yosys RTLIL::Const (with size() == N) // - IdString: yosys IdString - // - any: used in documentation to indicate that the type is unconstrained + // - any: used in documentation to indicate that the sort is unconstrained // - // nodes in the functional backend are either of type bit[N] or memory[N,M] (for some N, M: int) - // additionally, they can carry a constant of type int, Const[N] or IdString - // each node has a 'sort' field that stores the type of the node - // slice, zero_extend, sign_extend use the type field to store out_width + // nodes in the functional backend are either of sort bit[N] or memory[N,M] (for some N, M: int) + // additionally, they can carry a constant of sort int, Const[N] or IdString + // each node has a 'sort' field that stores the sort of the node + // slice, zero_extend, sign_extend use the sort field to store out_width enum class Fn { // invalid() = known-invalid/shouldn't happen value // TODO: maybe remove this and use e.g. std::optional instead? @@ -136,7 +136,7 @@ namespace Functional { // returns the name of a Fn value, as a string literal const char *fn_to_string(Fn); // Sort represents the sort or type of a node - // currently the only two types are signal/bit and memory + // currently the only two sorts are signal/bit and memory class Sort { std::variant> _v; public: @@ -144,11 +144,11 @@ namespace Functional { Sort(int addr_width, int data_width) : _v(std::make_pair(addr_width, data_width)) { } bool is_signal() const { return _v.index() == 0; } bool is_memory() const { return _v.index() == 1; } - // returns the width of a bitvector type, errors out for other types + // returns the width of a bitvector sort, errors out for other sorts int width() const { return std::get<0>(_v); } - // returns the address width of a bitvector type, errors out for other types + // returns the address width of a bitvector sort, errors out for other sorts int addr_width() const { return std::get<1>(_v).first; } - // returns the data width of a bitvector type, errors out for other types + // returns the data width of a bitvector sort, errors out for other sorts int data_width() const { return std::get<1>(_v).second; } bool operator==(Sort const& other) const { return _v == other._v; } unsigned int hash() const { return mkhash(_v); } @@ -160,22 +160,22 @@ namespace Functional { friend class Factory; public: IdString name; - IdString type; + IdString kind; Sort sort; private: - IRInput(IR &, IdString name, IdString type, Sort sort) - : name(name), type(type), sort(std::move(sort)) {} + IRInput(IR &, IdString name, IdString kind, Sort sort) + : name(name), kind(kind), sort(std::move(sort)) {} }; class IROutput { friend class Factory; IR &_ir; public: IdString name; - IdString type; + IdString kind; Sort sort; private: - IROutput(IR &ir, IdString name, IdString type, Sort sort) - : _ir(ir), name(name), type(type), sort(std::move(sort)) {} + IROutput(IR &ir, IdString name, IdString kind, Sort sort) + : _ir(ir), name(name), kind(kind), sort(std::move(sort)) {} public: Node value() const; bool has_value() const; @@ -186,12 +186,12 @@ namespace Functional { IR &_ir; public: IdString name; - IdString type; + IdString kind; Sort sort; private: std::variant _initial; - IRState(IR &ir, IdString name, IdString type, Sort sort) - : _ir(ir), name(name), type(type), sort(std::move(sort)) {} + IRState(IR &ir, IdString name, IdString kind, Sort sort) + : _ir(ir), name(name), kind(kind), sort(std::move(sort)) {} public: Node next_value() const; bool has_next_value() const; @@ -253,20 +253,20 @@ namespace Functional { Node operator[](int i); void topological_sort(); void forward_buf(); - IRInput const& input(IdString name, IdString type) const { return _inputs.at({name, type}); } + IRInput const& input(IdString name, IdString kind) const { return _inputs.at({name, kind}); } IRInput const& input(IdString name) const { return input(name, ID($input)); } - IROutput const& output(IdString name, IdString type) const { return _outputs.at({name, type}); } + IROutput const& output(IdString name, IdString kind) const { return _outputs.at({name, kind}); } IROutput const& output(IdString name) const { return output(name, ID($output)); } - IRState const& state(IdString name, IdString type) const { return _states.at({name, type}); } + IRState const& state(IdString name, IdString kind) const { return _states.at({name, kind}); } IRState const& state(IdString name) const { return state(name, ID($state)); } - bool has_input(IdString name, IdString type) const { return _inputs.count({name, type}); } - bool has_output(IdString name, IdString type) const { return _outputs.count({name, type}); } - bool has_state(IdString name, IdString type) const { return _states.count({name, type}); } - vector inputs(IdString type) const; + bool has_input(IdString name, IdString kind) const { return _inputs.count({name, kind}); } + bool has_output(IdString name, IdString kind) const { return _outputs.count({name, kind}); } + bool has_state(IdString name, IdString kind) const { return _states.count({name, kind}); } + vector inputs(IdString kind) const; vector inputs() const { return inputs(ID($input)); } - vector outputs(IdString type) const; + vector outputs(IdString kind) const; vector outputs() const { return outputs(ID($output)); } - vector states(IdString type) const; + vector states(IdString kind) const; vector states() const { return states(ID($state)); } vector all_inputs() const; vector all_outputs() const; @@ -364,12 +364,12 @@ namespace Functional { }; inline IR::Graph::Ref IR::mutate(Node n) { return _graph[n._ref.index()]; } inline Node IR::operator[](int i) { return Node(_graph[i]); } - inline Node IROutput::value() const { return Node(_ir._graph({name, type, false})); } - inline bool IROutput::has_value() const { return _ir._graph.has_key({name, type, false}); } - inline void IROutput::set_value(Node value) { log_assert(sort == value.sort()); _ir.mutate(value).assign_key({name, type, false}); } - inline Node IRState::next_value() const { return Node(_ir._graph({name, type, true})); } - inline bool IRState::has_next_value() const { return _ir._graph.has_key({name, type, true}); } - inline void IRState::set_next_value(Node value) { log_assert(sort == value.sort()); _ir.mutate(value).assign_key({name, type, true}); } + inline Node IROutput::value() const { return Node(_ir._graph({name, kind, false})); } + inline bool IROutput::has_value() const { return _ir._graph.has_key({name, kind, false}); } + inline void IROutput::set_value(Node value) { log_assert(sort == value.sort()); _ir.mutate(value).assign_key({name, kind, false}); } + inline Node IRState::next_value() const { return Node(_ir._graph({name, kind, true})); } + inline bool IRState::has_next_value() const { return _ir._graph.has_key({name, kind, true}); } + inline void IRState::set_next_value(Node value) { log_assert(sort == value.sort()); _ir.mutate(value).assign_key({name, kind, true}); } inline Node IR::iterator::operator*() { return Node(_ir->_graph[_index]); } inline arrow_proxy IR::iterator::operator->() { return arrow_proxy(**this); } // AbstractVisitor provides an abstract base class for visitors @@ -403,8 +403,8 @@ namespace Functional { virtual T arithmetic_shift_right(Node self, Node a, Node b) = 0; virtual T mux(Node self, Node a, Node b, Node s) = 0; virtual T constant(Node self, RTLIL::Const const & value) = 0; - virtual T input(Node self, IdString name, IdString type) = 0; - virtual T state(Node self, IdString name, IdString type) = 0; + virtual T input(Node self, IdString name, IdString kind) = 0; + virtual T state(Node self, IdString name, IdString kind) = 0; virtual T memory_read(Node self, Node mem, Node addr) = 0; virtual T memory_write(Node self, Node mem, Node addr, Node data) = 0; }; @@ -547,26 +547,26 @@ namespace Functional { log_assert(node.sort() == value.sort()); _ir.mutate(node).append_arg(value._ref); } - IRInput &add_input(IdString name, IdString type, Sort sort) { - auto [it, inserted] = _ir._inputs.emplace({name, type}, IRInput(_ir, name, type, std::move(sort))); + IRInput &add_input(IdString name, IdString kind, Sort sort) { + auto [it, inserted] = _ir._inputs.emplace({name, kind}, IRInput(_ir, name, kind, std::move(sort))); if (!inserted) log_error("input `%s` was re-defined", name.c_str()); return it->second; } - IROutput &add_output(IdString name, IdString type, Sort sort) { - auto [it, inserted] = _ir._outputs.emplace({name, type}, IROutput(_ir, name, type, std::move(sort))); + IROutput &add_output(IdString name, IdString kind, Sort sort) { + auto [it, inserted] = _ir._outputs.emplace({name, kind}, IROutput(_ir, name, kind, std::move(sort))); if (!inserted) log_error("output `%s` was re-defined", name.c_str()); return it->second; } - IRState &add_state(IdString name, IdString type, Sort sort) { - auto [it, inserted] = _ir._states.emplace({name, type}, IRState(_ir, name, type, std::move(sort))); + IRState &add_state(IdString name, IdString kind, Sort sort) { + auto [it, inserted] = _ir._states.emplace({name, kind}, IRState(_ir, name, kind, std::move(sort))); if (!inserted) log_error("state `%s` was re-defined", name.c_str()); return it->second; } Node value(IRInput const& input) { - return add(IR::NodeData(Fn::input, std::pair(input.name, input.type)), input.sort, {}); + return add(IR::NodeData(Fn::input, std::pair(input.name, input.kind)), input.sort, {}); } Node value(IRState const& state) { - return add(IR::NodeData(Fn::state, std::pair(state.name, state.type)), state.sort, {}); + return add(IR::NodeData(Fn::state, std::pair(state.name, state.kind)), state.sort, {}); } void suggest_name(Node node, IdString name) { _ir.mutate(node).sparse_attr() = name;