Skip to content

[RISCV][TableGen] Generate RISCVTargetParserDef.inc from the new RISCVExtension tblgen information. #89335

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

Merged
merged 6 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions llvm/test/TableGen/riscv-target-def.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// RUN: llvm-tblgen -gen-riscv-target-def -I %p/../../include %s | FileCheck %s

include "llvm/Target/Target.td"

class RISCVExtension<string name, int major, int minor, string fieldname,
string desc, list<SubtargetFeature> implies = [],
string value = "true">
: SubtargetFeature<name, fieldname, value, desc, implies> {
int MajorVersion = major;
int MinorVersion = minor;
bit Experimental = false;
}

def FeatureStdExtI
: RISCVExtension<"i", 2, 1, "HasStdExtI",
"'I' (Base Integer Instruction Set)">;

def FeatureStdExtZicsr
: RISCVExtension<"zicsr", 2, 0, "HasStdExtZicsr",
"'zicsr' (CSRs)">;

def FeatureStdExtZifencei
: RISCVExtension<"zifencei", 2, 0, "HasStdExtZifencei",
"'Zifencei' (fence.i)">;

def Feature32Bit
: SubtargetFeature<"32bit", "IsRV32", "true", "Implements RV32">;
def Feature64Bit
: SubtargetFeature<"64bit", "IsRV64", "true", "Implements RV64">;

// Dummy feature that isn't an extension.
def FeatureDummy
: SubtargetFeature<"dummy", "Dummy", "true", "Dummy">;

class RISCVProcessorModel<string n,
SchedMachineModel m,
list<SubtargetFeature> f,
list<SubtargetFeature> tunef = [],
string default_march = "">
: ProcessorModel<n, m, f, tunef> {
string DefaultMarch = default_march;
}

class RISCVTuneProcessorModel<string n,
SchedMachineModel m,
list<SubtargetFeature> tunef = [],
list<SubtargetFeature> f = []>
: ProcessorModel<n, m, f,tunef>;

def GENERIC_RV32 : RISCVProcessorModel<"generic-rv32",
NoSchedModel,
[Feature32Bit,
FeatureStdExtI]>;
def GENERIC_RV64 : RISCVProcessorModel<"generic-rv64",
NoSchedModel,
[Feature64Bit,
FeatureStdExtI]>;
def GENERIC : RISCVTuneProcessorModel<"generic", NoSchedModel>;


def ROCKET_RV32 : RISCVProcessorModel<"rocket-rv32",
NoSchedModel,
[Feature32Bit,
FeatureStdExtI,
FeatureStdExtZifencei,
FeatureStdExtZicsr,
FeatureDummy]>;
def ROCKET_RV64 : RISCVProcessorModel<"rocket-rv64",
NoSchedModel,
[Feature64Bit,
FeatureStdExtI,
FeatureStdExtZifencei,
FeatureStdExtZicsr,
FeatureDummy]>;
def ROCKET : RISCVTuneProcessorModel<"rocket",
NoSchedModel>;

// CHECK: #ifndef PROC
// CHECK: #define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_UNALIGNED_ACCESS)
// CHECK: #endif

// CHECK: PROC(GENERIC_RV32, {"generic-rv32"}, {"rv32i2p1"}, 0)
// CHECK: PROC(GENERIC_RV64, {"generic-rv64"}, {"rv64i2p1"}, 0)
// CHECK: PROC(ROCKET_RV32, {"rocket-rv32"}, {"rv32i2p1_zicsr2p0_zifencei2p0"}, 0)
// CHECK: PROC(ROCKET_RV64, {"rocket-rv64"}, {"rv64i2p1_zicsr2p0_zifencei2p0"}, 0)

// CHECK: #undef PROC

// CHECK: #ifndef TUNE_PROC
// CHECK: #define TUNE_PROC(ENUM, NAME)
// CHECK: #endif

// CHECK: TUNE_PROC(GENERIC, "generic")
// CHECK: TUNE_PROC(ROCKET, "rocket")

// CHECK: #undef TUNE_PROC
55 changes: 32 additions & 23 deletions llvm/utils/TableGen/RISCVTargetDefEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,41 @@

using namespace llvm;

using ISAInfoTy = llvm::Expected<std::unique_ptr<RISCVISAInfo>>;

// We can generate march string from target features as what has been described
// in RISC-V ISA specification (version 20191213) 'Chapter 27. ISA Extension
// Naming Conventions'.
//
// This is almost the same as RISCVFeatures::parseFeatureBits, except that we
// get feature name from feature records instead of feature bits.
static std::string getMArch(const Record &Rec) {
std::vector<std::string> FeatureVector;
unsigned XLen = 32;
static void printMArch(raw_ostream &OS, const Record &Rec) {
std::map<std::string, RISCVISAInfo::ExtensionVersion,
RISCVISAInfo::ExtensionComparator>
Copy link
Contributor

@wangpc-pp wangpc-pp Apr 19, 2024

Choose a reason for hiding this comment

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

Maybe we should move ExtensionComparator to a suitable place so that we don't depend on RISCVISAInfo.h.
Edit: there is a cyclic dependency IIUC...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I will eventually. I don't think there's a suitable place other than creating a new RISC-V specific file.

Extensions;
unsigned XLen = 0;

// Convert features to FeatureVector.
for (auto *Feature : Rec.getValueAsListOfDefs("Features")) {
StringRef FeatureName = Feature->getValueAsString("Name");
if (llvm::RISCVISAInfo::isSupportedExtensionFeature(FeatureName))
FeatureVector.push_back((Twine("+") + FeatureName).str());
else if (FeatureName == "64bit")
if (Feature->isSubClassOf("RISCVExtension")) {
unsigned Major = Feature->getValueAsInt("MajorVersion");
unsigned Minor = Feature->getValueAsInt("MinorVersion");
Extensions[FeatureName.str()] = {Major, Minor};
} else if (FeatureName == "64bit") {
assert(XLen == 0 && "Already determined XLen");
XLen = 64;
} else if (FeatureName == "32bit") {
assert(XLen == 0 && "Already determined XLen");
XLen = 32;
}
}

ISAInfoTy ISAInfo = llvm::RISCVISAInfo::parseFeatures(XLen, FeatureVector);
if (!ISAInfo)
report_fatal_error("Invalid features");
assert(XLen != 0 && "Unable to determine XLen");

OS << "rv" << XLen;

// RISCVISAInfo::toString will generate a march string with all the extensions
// we have added to it.
return (*ISAInfo)->toString();
ListSeparator LS("_");
for (auto const &Ext : Extensions)
OS << LS << Ext.first << Ext.second.Major << 'p' << Ext.second.Minor;
}

static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) {
Expand All @@ -54,12 +61,6 @@ static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) {

// Iterate on all definition records.
for (const Record *Rec : RK.getAllDerivedDefinitions("RISCVProcessorModel")) {
std::string MArch = Rec->getValueAsString("DefaultMarch").str();

// Compute MArch from features if we don't specify it.
if (MArch.empty())
MArch = getMArch(*Rec);

bool FastScalarUnalignedAccess =
any_of(Rec->getValueAsListOfDefs("Features"), [&](auto &Feature) {
return Feature->getValueAsString("Name") == "unaligned-scalar-mem";
Expand All @@ -73,9 +74,17 @@ static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) {
bool FastUnalignedAccess =
FastScalarUnalignedAccess && FastVectorUnalignedAccess;

OS << "PROC(" << Rec->getName() << ", "
<< "{\"" << Rec->getValueAsString("Name") << "\"}, "
<< "{\"" << MArch << "\"}, " << FastUnalignedAccess << ")\n";
OS << "PROC(" << Rec->getName() << ", {\"" << Rec->getValueAsString("Name")
<< "\"}, {\"";

StringRef MArch = Rec->getValueAsString("DefaultMarch");

// Compute MArch from features if we don't specify it.
if (MArch.empty())
printMArch(OS, *Rec);
else
OS << MArch;
OS << "\"}, " << FastUnalignedAccess << ")\n";
}
OS << "\n#undef PROC\n";
OS << "\n";
Expand Down