1*06c3fb27SDimitry Andric //===- RISCVTargetDefEmitter.cpp - Generate lists of RISC-V CPUs ----------===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric // 9bdd1243dSDimitry Andric // This tablegen backend emits the include file needed by the target 10bdd1243dSDimitry Andric // parser to parse the RISC-V CPUs. 11bdd1243dSDimitry Andric // 12bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 13bdd1243dSDimitry Andric 14bdd1243dSDimitry Andric #include "llvm/Support/RISCVISAInfo.h" 15bdd1243dSDimitry Andric #include "llvm/TableGen/Record.h" 16*06c3fb27SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 17bdd1243dSDimitry Andric 18bdd1243dSDimitry Andric using namespace llvm; 19bdd1243dSDimitry Andric 20bdd1243dSDimitry Andric using ISAInfoTy = llvm::Expected<std::unique_ptr<RISCVISAInfo>>; 21bdd1243dSDimitry Andric 22bdd1243dSDimitry Andric // We can generate march string from target features as what has been described 23*06c3fb27SDimitry Andric // in RISC-V ISA specification (version 20191213) 'Chapter 27. ISA Extension 24bdd1243dSDimitry Andric // Naming Conventions'. 25bdd1243dSDimitry Andric // 26bdd1243dSDimitry Andric // This is almost the same as RISCVFeatures::parseFeatureBits, except that we 27bdd1243dSDimitry Andric // get feature name from feature records instead of feature bits. 28bdd1243dSDimitry Andric static std::string getMArch(const Record &Rec) { 29bdd1243dSDimitry Andric std::vector<std::string> FeatureVector; 30*06c3fb27SDimitry Andric unsigned XLen = 32; 31bdd1243dSDimitry Andric 32bdd1243dSDimitry Andric // Convert features to FeatureVector. 33bdd1243dSDimitry Andric for (auto *Feature : Rec.getValueAsListOfDefs("Features")) { 34bdd1243dSDimitry Andric StringRef FeatureName = Feature->getValueAsString("Name"); 35bdd1243dSDimitry Andric if (llvm::RISCVISAInfo::isSupportedExtensionFeature(FeatureName)) 36bdd1243dSDimitry Andric FeatureVector.push_back((Twine("+") + FeatureName).str()); 37bdd1243dSDimitry Andric else if (FeatureName == "64bit") 38bdd1243dSDimitry Andric XLen = 64; 39bdd1243dSDimitry Andric } 40bdd1243dSDimitry Andric 41bdd1243dSDimitry Andric ISAInfoTy ISAInfo = llvm::RISCVISAInfo::parseFeatures(XLen, FeatureVector); 42bdd1243dSDimitry Andric if (!ISAInfo) 43bdd1243dSDimitry Andric report_fatal_error("Invalid features"); 44bdd1243dSDimitry Andric 45bdd1243dSDimitry Andric // RISCVISAInfo::toString will generate a march string with all the extensions 46bdd1243dSDimitry Andric // we have added to it. 47bdd1243dSDimitry Andric return (*ISAInfo)->toString(); 48bdd1243dSDimitry Andric } 49bdd1243dSDimitry Andric 50*06c3fb27SDimitry Andric static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) { 51bdd1243dSDimitry Andric OS << "#ifndef PROC\n" 52bdd1243dSDimitry Andric << "#define PROC(ENUM, NAME, DEFAULT_MARCH)\n" 53bdd1243dSDimitry Andric << "#endif\n\n"; 54bdd1243dSDimitry Andric 55bdd1243dSDimitry Andric // Iterate on all definition records. 56bdd1243dSDimitry Andric for (const Record *Rec : RK.getAllDerivedDefinitions("RISCVProcessorModel")) { 57bdd1243dSDimitry Andric std::string MArch = Rec->getValueAsString("DefaultMarch").str(); 58bdd1243dSDimitry Andric 59bdd1243dSDimitry Andric // Compute MArch from features if we don't specify it. 60bdd1243dSDimitry Andric if (MArch.empty()) 61bdd1243dSDimitry Andric MArch = getMArch(*Rec); 62bdd1243dSDimitry Andric 63bdd1243dSDimitry Andric OS << "PROC(" << Rec->getName() << ", " 64bdd1243dSDimitry Andric << "{\"" << Rec->getValueAsString("Name") << "\"}, " 65bdd1243dSDimitry Andric << "{\"" << MArch << "\"})\n"; 66bdd1243dSDimitry Andric } 67bdd1243dSDimitry Andric OS << "\n#undef PROC\n"; 68bdd1243dSDimitry Andric OS << "\n"; 69bdd1243dSDimitry Andric OS << "#ifndef TUNE_PROC\n" 70bdd1243dSDimitry Andric << "#define TUNE_PROC(ENUM, NAME)\n" 71bdd1243dSDimitry Andric << "#endif\n\n"; 72bdd1243dSDimitry Andric OS << "TUNE_PROC(GENERIC, \"generic\")\n"; 73bdd1243dSDimitry Andric 74bdd1243dSDimitry Andric for (const Record *Rec : 75bdd1243dSDimitry Andric RK.getAllDerivedDefinitions("RISCVTuneProcessorModel")) { 76bdd1243dSDimitry Andric OS << "TUNE_PROC(" << Rec->getName() << ", " 77bdd1243dSDimitry Andric << "\"" << Rec->getValueAsString("Name") << "\")\n"; 78bdd1243dSDimitry Andric } 79bdd1243dSDimitry Andric 80bdd1243dSDimitry Andric OS << "\n#undef TUNE_PROC\n"; 81bdd1243dSDimitry Andric } 82*06c3fb27SDimitry Andric 83*06c3fb27SDimitry Andric static TableGen::Emitter::Opt X("gen-riscv-target-def", EmitRISCVTargetDef, 84*06c3fb27SDimitry Andric "Generate the list of CPU for RISCV"); 85