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

Functional Backend #4536

merged 93 commits into from
Sep 6, 2024

Conversation

aiju
Copy link
Contributor

@aiju aiju commented Aug 13, 2024

Add a new intermediate representation to be used for writing backends for functional language-shaped targets, conversion code from RTLIL, and three example backends (C++, SMTLIB and Rosette).

@povik
Copy link
Member

povik commented Aug 13, 2024

Is this preserving undefined bits, or is this more of a synthesis target like CXXRTL?

@aiju
Copy link
Contributor Author

aiju commented Aug 13, 2024

Is this preserving undefined bits, or is this more of a synthesis target like CXXRTL?

Currently 'x' bits are treated as 'dont care' (mostly set to 0), which I think matches the existing formal infrastructure. The idea is that users can use xprop if they want 'x' behaviour.

@povik
Copy link
Member

povik commented Aug 13, 2024

FWIW a write-up on how this differs from CXXRTL (apart from this being language-agnostic) would help me understand what this is. I know you all are busy though.

@aiju
Copy link
Contributor Author

aiju commented Aug 13, 2024

FWIW a write-up on how this differs from CXXRTL (apart from this being language-agnostic) would help me understand what this is. I know you all are busy though.

I don't actually know how CXXRTL works in detail but the key point is that this is intended to match formal semantics and I think CXXRTL is a mix of simulation and synthesis semantics.

@whitequark
Copy link
Member

I don't actually know how CXXRTL works in detail but the key point is that this is intended to match formal semantics and I think CXXRTL is a mix of simulation and synthesis semantics.

CXXRTL implements synthesis semantics only, to my best knowledge. (Obviously, sometimes that would match simulation semantics.)

@georgerennie
Copy link
Collaborator

georgerennie commented Aug 14, 2024

Currently 'x' bits are treated as 'dont care' (mostly set to 0), which I think matches the existing formal infrastructure

Is this just for the C++ target or also for smtlib/rosette? For C++ which requires concrete values this obviously makes sense to set to 0, but if being used with smtlib/rosette for verification surely you want to leave xs as symbolic variables that can take the value 0 or 1 (pseudo primary inputs, the same as $anyseq) to verify all allowed behaviours?

Existing formal infrastructure by default models xs in this way for this reason (although doesn't model x-prop semantics unless xprop is used)

@KrystalDelusion
Copy link
Member

smtlib/rosette (currently) pull down to 0

@aiju
Copy link
Contributor Author

aiju commented Aug 21, 2024

Currently 'x' bits are treated as 'dont care' (mostly set to 0), which I think matches the existing formal infrastructure

Is this just for the C++ target or also for smtlib/rosette? For C++ which requires concrete values this obviously makes sense to set to 0, but if being used with smtlib/rosette for verification surely you want to leave xs as symbolic variables that can take the value 0 or 1 (pseudo primary inputs, the same as $anyseq) to verify all allowed behaviours?

Existing formal infrastructure by default models xs in this way for this reason (although doesn't model x-prop semantics unless xprop is used)

Oh I didn't know that's how it works. If it's just constants then that's probably not too difficult to add as an option. I bounced off x-semantics because adding x-propagation seemed too complicated and enforcing 2-value logic seemed like the easiest solution.

jix and others added 21 commits August 21, 2024 10:58
This adds a generic non-recursive implementation of Tarjan's linear time
SCC algorithm that produces components in topological order. It can be
instantiated to work directly on any graph representation for which the
enumerate_nodes and enumerate_successors interface can be implemented.
When implementing custom log_... functions or custom overloads for the
core log functions like log_signal it is necessary to return `char *`
that are valid long enough.

The log_... functions implemented in log.cc use either `log_id_cache` or
`string_buf` which both are cleared on log_pop.

This commit adds a public `log_str` function which stores its argument
in the `log_id_cache` and returns the stored copy, such that custom
log functions outside of log.cc can also create strings that remain
valid until the next `log_pop`.
This is already supported by `SigSpec` and since both `SigChunk` and
`SigSpec` implement `extract` which is the multi-bit variant of this,
there is no good reason for `SigChunk` to not support
`SigBit operator[](int offset)`.
It adds `DriveBit`, `DriveChunk` and `DriveSpec` types which are similar
to `SigBit`, `SigChunk` and `SigSpec` but can also directly represent
cell ports, undriven bits and multiple drivers. For indexing an RTLIL
module and for querying signal drivers it comes with a `DriverMap` type
which is somewhat similar to a `SigMap` but is guaranteed to produce
signal drivers as returned representatives.

A `DriverMap` can also optionally preserve connections via intermediate
wires (e.g. querying the driver of a cell input port will return a
connected intermediate wire, querying the driver of that wire will
return the cell output port that's driving the wire).
if(addr % 8 == 7) printf("\n");
}
printf("\n");
//log_abort();

Check notice

Code scanning / CodeQL

Commented-out code Note test

This comment appears to contain commented-out code.
Comment on lines +96 to +97
//addr_t length = std::min((1<<addr_width) - low, length_dist(rnd));
//addr_t high = low + length - 1;

Check notice

Code scanning / CodeQL

Commented-out code Note test

This comment appears to contain commented-out code.
Comment on lines +133 to +139
/*
MemContentsTest test(8, 16);

std::random_device seed_dev;
std::mt19937 rnd(23); //seed_dev());
test.run(rnd, 1000);
*/

Check notice

Code scanning / CodeQL

Commented-out code Note test

This comment appears to contain commented-out code.
inline DriveChunkMultiple::DriveChunkMultiple(DriveBitMultiple const &bit)
: width_(1)
{
for (auto const &bit : bit.multiple())

Check notice

Code scanning / CodeQL

Declaration hides parameter Note

Local variable 'bit' hides a
parameter of the same name
.
} else if(cellType == ID($demux)) {
int width = parameters.at(ID(WIDTH)).as_int();
int s_width = parameters.at(ID(S_WIDTH)).as_int();
int y_width = width << s_width;

Check notice

Code scanning / CodeQL

Declaration hides variable Note

Variable y_width hides another variable of the same name (on
line 253
).
// check if the iterator points to a range overlapping with [begin_addr, end_addr)
bool _range_overlaps(std::map<addr_t, RTLIL::Const>::iterator it, addr_t begin_addr, addr_t end_addr) const;
// return the offset the addr would have in the range at `it`
size_t _range_offset(std::map<addr_t, RTLIL::Const>::iterator it, addr_t addr) const { return (addr - it->first) * _data_width; }

Check failure

Code scanning / CodeQL

Multiplication result converted to larger type High

Multiplication result may overflow 'unsigned int' before it is converted to 'size_t'.
public:
SExpr(std::string a) : _v(std::move(a)) {}
SExpr(const char *a) : _v(a) {}
// FIXME: should maybe be defined for all integral types

Check notice

Code scanning / CodeQL

FIXME comment Note

FIXME comment: should maybe be defined for all integral types

namespace SExprUtil {
// A little hack so that `using SExprUtil::list` lets you import a shortcut to `SExpr::list`
template<typename... Args> SExpr list(Args&&... args) {

Check notice

Code scanning / CodeQL

Unused local variable Note

Variable args is not used.

namespace SExprUtil {
// A little hack so that `using SExprUtil::list` lets you import a shortcut to `SExpr::list`
template<typename... Args> SExpr list(Args&&... args) {

Check notice

Code scanning / CodeQL

Unused static variable Note

Static variable args is never read.
}


void execute(std::vector<std::string> args, RTLIL::Design *design) override

Check warning

Code scanning / CodeQL

Poorly documented large function Warning

Poorly documented function: fewer than 2% comments for a function of 221 lines.
@mmicko mmicko marked this pull request as ready for review September 6, 2024 07:52
Copy link
Member

@KrystalDelusion KrystalDelusion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing smtlib and rosette tests, but that can be fixed later.

@mmicko mmicko merged commit b20df72 into main Sep 6, 2024
29 checks passed
@mmicko mmicko deleted the functional branch September 6, 2024 08:05
template<size_t n>
class Signal {
template<size_t m> friend class Signal;
std::array<bool, n> _bits;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw why this instead of std::bitset<n>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i didn't know about std::bitset :) i guess rewriting it to use that would simplify the code a bit, but would still need to implement addition, etc


struct FunctionalTestGeneric : public Pass
{
FunctionalTestGeneric() : Pass("test_generic", "test the generic compute graph") {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we rename this to test_cgraph or similar. This has the potential to confuse people

Copy link
Contributor Author

@aiju aiju Sep 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea i'm happy to rename this, also test_generic.cc needs some cleanup that i forgot to do...

// any nodes untouched by this point are dead code and will be removed by permute
_graph.permute(perm);
if(scc) log_error("The design contains combinational loops. This is not supported by the functional backend. "
"Try `scc -select; simplemap; select -clear` to avoid this error.\n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be an outstanding TODO but simplemap will leave around gate cells which are unsupported by the functional backend as of yet

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah gate-level cells was on my TODO list but i didn't get around to it for the deliverable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants