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

Initial VAY draft #4498

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft

Initial VAY draft #4498

wants to merge 2 commits into from

Conversation

clairexen
Copy link
Member

This adds the build config variable ENABLE_VIRTUAL_APIS. When enabled, the build will produce a vay executable instead of a yosys executable. (VAY stands for Virtual APIs in Yosys, and is pronounced like "way".)

In a "vay" build, cells can be of different types, and the Cell API is providing virtual methods that the individual cell types can override.

The goal is to refactor most of yosys to use the virtual methods instead of accessing Cell members directly, or disable commands that would be hard to refactor. Especially coarse-grain front-end commands like read_verilog and proc would likely not be included in vay, because they represent a large code-base that would potentially be hard to refactor in that way.

In the end we want to have a vay command in yosys, that will exec vay to replace the yosys process, and automatically saves and restores the state, including passing open file handles for things like the script being executed. This allows us to switch from yosys to vay when going from coarse-grain to fine-grain synthesis, enabling more efficient representations of fine-grain netlists, at the cost of the overhead of virtual method call dispatch.

Signed-off-by: Claire Xenia Wolf <claire@clairexen.net>
@whitequark
Copy link
Member

In the end we want to have a vay command in yosys, that will exec vay to replace the yosys process, and automatically saves and restores the state, including passing open file handles for things like the script being executed.

How will this work on Windows or WASI?

@clairexen
Copy link
Member Author

clairexen commented Jul 18, 2024 via email

@whitequark
Copy link
Member

That could work, though in that case there's no need to have the execve dance at all.

@clairexen
Copy link
Member Author

I would expect that a fair amount of cleanup will be necessary for this to work. The execve dance would be quick and easy to implement, as a first proof-of-concept.

@widlarizer
Copy link
Collaborator

So, this seems like explicitly an alternative to #4461 ("my approach") and we can conceptually compare them to some extent. Take the hot loop in opt_expr. You have a vector of cells, and you iterate over them.

Currently: You load the type field. If it's equal to a certain type, you look at the corresponding parameters and connections by looking up their identifiers in dictionaries

This PR: You dynamic_cast the cell pointer to a pointer of a certain C++ type. The compiler knows this type to be final, so it devirtualizes calls to member functions, and you get low overhead access to the cell type, parameters and connections.

My approach: You load the type field. If it's equal to a certain type, you look at the corresponding parameters and connections by calling non-virtual calls to functions that are conditionall on the cell type. The compiler inlines and const propagates this (I hope) so you get low overhead direct access to the parameters and connections.

My approach requires codegen for boilerplate, this PR suggests a yosys restart and passing of live resources, so both bring some codebase complexity. My concern is for the dynamic_cast overhead. As for real world inspiration, LLVM famously uses dynamic_casts all over the place, while the zig compiler represents its core structures as tagged union of structs, aims to replace LLVM for many use cases, and it's going well

@whitequark
Copy link
Member

whitequark commented Jul 18, 2024

As for real world inspiration, LLVM famously uses dynamic_casts all over the place

This is not true. LLVM uses dyn_cast, which is a very low overhead mechanism that does not require RTTI. (You can build LLVM with no RTTI or exceptions; for example my Wasm build of it is doing just that.)

(Zig also should not be used as an example here more generally, but I'm not going to go too off-topic while explaining why.)

@whitequark
Copy link
Member

I think everyone in this thread would benefit from reading how "LLVM-style RTTI" (unrelated to the C++'s built-in RTTI mechanism) actually works, which is documented here.

Signed-off-by: Claire Xenia Wolf <claire@clairexen.net>
@widlarizer
Copy link
Collaborator

From yesterday's discussion on a call:

A two binary solution is temporarily desirable because switching fully to VAY will bring a performance hit in unmodified code which calls virtual methods on Cell* rather than the final types. High priority hot code paths (opt, fine-grained post techmap) will be reimplemented / modified to use dynamic casts to avoid this perf hit. Memory efficiency is more important than runtime. As pointed out by whitequark, LLVM implements custom dynamic casts over custom kind/opcode fields, so it seems like we can do something similar by enumerating cell types.

This approach fits the bill better in that regard than mine, since I expected to keep a vector of tagged unions, which is memory inefficient when those structs are heterogeneous in size, which currently they are, and it would be a lot of work to do the "extra memory" trick to move less hot struct members to a storage external to the struct.

Both approaches should be brought into a state where their performance and complexity can be evaluated.

This approach counts on future codegen, as does mine. This should allow easy changes later on, partially through replacing member access with method calls.

The scope of my approach doesn't currently cover directly using SigBits for fine-grained cell ports. Storing SigBits instead of SigSpecs violates the current interface and requires realizable workarounds. Claire brought up that it may be done similarly to how logging strings work now

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.

3 participants