Skip to content

[Backend][BLIF] Automatic generation of blif files #872

Open
Carmine50 wants to merge 31 commits into
mainfrom
feature/crizzi/automatic-blif-generation
Open

[Backend][BLIF] Automatic generation of blif files #872
Carmine50 wants to merge 31 commits into
mainfrom
feature/crizzi/automatic-blif-generation

Conversation

@Carmine50
Copy link
Copy Markdown
Collaborator

The following PR introduces a BLIF Generator, which automatically generates BLIF files of dataflow units.

The BLIF generator is automatically called by the BLIF file manager when a blif file is not found in the blif library.

Please refer to the doc for more information about it

This PR also fixes bugs present in the HandshakeToSynth conversion pass, it adds new attributes in the hw flattening pass, and adds yosys in the dynamatic flow.

@Jiahui17
Copy link
Copy Markdown
Member

I fill like it is quite redundant to store the path to abc and yosys inside the config class.

I think it makes more sense to configure the bianry location at compile time and maybe fall back to PATH

So we don’t need to use a variant differentiate the config between blif vs. verilog

}

private:
std::string rtlConfigPath; /// Absolute path to the JSON RTL config file.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why does this still need RTL config?

Comment on lines +35 to +40
/// Parameters for Backend generation.
struct BackendParams {
std::string rtlConfigPath; /// Absolute path to the JSON RTL config.
std::string dynamaticRoot; /// Project root for $DYNAMATIC substitution.
std::string outputBaseDir; /// Base directory for per-module output.
};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

They could be just the private members of the generator class itself


namespace dynamatic {

class BackendGenerator {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

UnitRTLGenerator?


namespace dynamatic {

class BackendGenerator {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Usage example

const std::string &getModuleName() const { return moduleName; }
/// Verilog backend: returns the generated .v files.
/// BLIF backend: returns a single-element vector with the .blif file path.
const std::vector<std::string> &getOutputFiles() const { return outputFiles; }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is not clear to me here if we should use one generator instance for generating many units or one generator instance per one unit?

Comment on lines +415 to +419
std::filesystem::permissions(scriptPath,
std::filesystem::perms::owner_exec |
std::filesystem::perms::owner_read |
std::filesystem::perms::owner_write,
std::filesystem::perm_options::add);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why do you need this?

Comment on lines +428 to +445
// Check if ABC executable is configured.
#if !defined(DYNAMATIC_ABC_EXECUTABLE)
// If not configured, check that there is an "abc" executable in the system
// PATH.
if (system("which abc > /dev/null 2>&1") != 0) {
llvm::errs() << "ABC executable not found. Please install ABC or "
"re-build Dynamatic with ABC enabled.\n";
return false;
}
abcExecutable = "abc";
#else
abcExecutable = DYNAMATIC_ABC_EXECUTABLE;
if (!std::filesystem::exists(abcExecutable)) {
llvm::errs() << "ABC executable not found at configured path: "
<< abcExecutable << "\n";
return false;
}
#endif
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

separate function

Comment on lines +375 to +393
std::string yosysExecutable;
// Check if Yosys executable is configured.
#if !defined(DYNAMATIC_YOSYS_EXECUTABLE)
// If not configured, check that there is a "yosys" executable in the system
// PATH.
if (system("which yosys > /dev/null 2>&1") != 0) {
llvm::errs() << "Yosys executable not found. Please install Yosys or "
"re-build Dynamatic with Yosys enabled.\n";
return false;
}
yosysExecutable = "yosys";
#else
yosysExecutable = DYNAMATIC_YOSYS_EXECUTABLE;
if (!std::filesystem::exists(yosysExecutable)) {
llvm::errs() << "Yosys executable not found at configured path: "
<< yosysExecutable << "\n";
return false;
}
#endif
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

separate function in the anonymous namespace

Comment on lines +86 to +90
if (Operation *defOp = outputVal.getDefiningOp()) {
defOp->setAttr("hw.module_name", modName);
defOp->setAttr("hw.port_name", portName);
}
++outIdx;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't understand where are these attributes actually used

Comment on lines +266 to +271
std::ifstream configFile(rtlConfigPath);
if (!configFile.is_open()) {
llvm::errs() << "BackendGenerator: cannot open config: " << rtlConfigPath
<< "\n";
return false;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why don't you use this?

/// Represents the content of one or more RTL configuration files; essentially a
/// list of RTL component descriptions along with a matching logic to select a
/// description (if any) that can concretize a specific component configuration.
class RTLConfiguration {
public:
/// Default constructor.
RTLConfiguration() = default;
/// Attempts to deserialize the JSON-formatted RTL configuration file at the
/// provided location and add all its component descriptions to the existing
/// list.
LogicalResult addComponentsFromJSON(StringRef filepath);
/// Determines whether any RTL component is compatible with the request.
bool hasMatchingComponent(const RTLRequest &request);
/// Tries to find an RTL component that is compatible with the request.
/// Returns a heap-allocated match to the first matching component (in
/// JSON-parsing-order) if one exists; otherwise returs nullptr.
RTLMatch *getMatchingComponent(const RTLRequest &request);
/// Finds all RTL components compatible with the request and pushes
/// corresponding heap-allocated matches to the vector (in
/// JSON-parsing-order).
void findMatchingComponents(const RTLRequest &request,
std::vector<RTLMatch *> &matches) const;
/// Determines whether the RTL configuration has any component with a timing
/// model compatible with the match object. Returns the first compatible model
/// (in component and model list order), if any exists.
const RTLComponent::Model *getModel(const RTLRequest &request) const;
RTLConfiguration(RTLConfiguration &&) noexcept = default;
RTLConfiguration &operator=(RTLConfiguration &&) noexcept = default;
private:
/// List of RTL component descriptions parsed from one or many RTL
/// configuration files.
std::vector<RTLComponent> components;
};
} // namespace dynamatic

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.

2 participants