From a5ff3e7e612fd7a59e769ee851bec5c078938911 Mon Sep 17 00:00:00 2001 From: Dmitry Bushev Date: Wed, 25 Dec 2024 13:26:10 +0000 Subject: [PATCH] [snippy] Replace hardcoded RAM/ROM to list of memory regions --- .../snippy-plugin-layout-store-only.yaml | 2 +- .../Inputs/snippy-plugin-layout.yaml | 2 +- .../include/snippy/Generator/Interpreter.h | 13 +- .../include/snippy/Generator/SimRunner.h | 17 +- .../include/snippy/Simulator/Simulator.h | 20 +-- .../include/snippy/Support/DiagnosticInfo.h | 1 + .../llvm-snippy/lib/Generator/Interpreter.cpp | 162 +++++++----------- .../llvm-snippy/lib/Generator/SimRunner.cpp | 43 +---- .../Generator/SimulatorContextWrapperPass.cpp | 8 +- .../lib/Simulator/RISCVSimulator.cpp | 26 +-- .../llvm-snippy/lib/Simulator/Simulator.cpp | 84 +++++++-- .../lib/Simulator/Transactions.cpp | 2 +- 12 files changed, 172 insertions(+), 208 deletions(-) diff --git a/llvm/test/tools/llvm-snippy/Inputs/snippy-plugin-layout-store-only.yaml b/llvm/test/tools/llvm-snippy/Inputs/snippy-plugin-layout-store-only.yaml index 81a1bc222db3..7d5f9cfecddd 100644 --- a/llvm/test/tools/llvm-snippy/Inputs/snippy-plugin-layout-store-only.yaml +++ b/llvm/test/tools/llvm-snippy/Inputs/snippy-plugin-layout-store-only.yaml @@ -11,7 +11,7 @@ sections: ACCESS: rw - no: 3 VMA: 0x80000000 - SIZE: 0x400000 + SIZE: 0x10c8 LMA: 0x80000000 ACCESS: rw diff --git a/llvm/test/tools/llvm-snippy/Inputs/snippy-plugin-layout.yaml b/llvm/test/tools/llvm-snippy/Inputs/snippy-plugin-layout.yaml index 2f11d1f0c130..bbb6c484a08f 100644 --- a/llvm/test/tools/llvm-snippy/Inputs/snippy-plugin-layout.yaml +++ b/llvm/test/tools/llvm-snippy/Inputs/snippy-plugin-layout.yaml @@ -11,7 +11,7 @@ sections: ACCESS: rw - no: 3 VMA: 0x80000000 - SIZE: 0x400000 + SIZE: 0x10c8 LMA: 0x80000000 ACCESS: rw diff --git a/llvm/tools/llvm-snippy/include/snippy/Generator/Interpreter.h b/llvm/tools/llvm-snippy/include/snippy/Generator/Interpreter.h index a426e79d38b8..ee1d76f8d24c 100644 --- a/llvm/tools/llvm-snippy/include/snippy/Generator/Interpreter.h +++ b/llvm/tools/llvm-snippy/include/snippy/Generator/Interpreter.h @@ -95,24 +95,15 @@ class Interpreter final { void initTransactionMechanism(); void dumpOneRange(NamedMemoryRange Range, raw_fd_ostream &OS) const; + bool coveredByMemoryRegion(MemAddr Start, MemAddr Size) const; public: uint64_t getProgEnd() const { return ProgEnd; } - uint64_t getRomStart() const { return Env.SimCfg.RomStart; } - uint64_t getRamStart() const { return Env.SimCfg.RamStart; } - - uint64_t getRomSize() const { return Env.SimCfg.RomSize; } - uint64_t getRamSize() const { return Env.SimCfg.RamSize; } - - uint64_t getRomEnd() const { return getRomStart() + getRomSize(); } - uint64_t getRamEnd() const { return getRamStart() + getRamSize(); } - bool endOfProg() const; static SimulationEnvironment createSimulationEnvironment( SnippyProgramContext &SPC, const TargetSubtargetInfo &ST, - const GeneratorSettings &Settings, const MemoryConfig &MemCfg, - TargetGenContextInterface &TgtCtx); + const GeneratorSettings &Settings, TargetGenContextInterface &TgtCtx); static std::unique_ptr createSimulatorForTarget( const SnippyTarget &TGT, const TargetSubtargetInfo &Subtarget, diff --git a/llvm/tools/llvm-snippy/include/snippy/Generator/SimRunner.h b/llvm/tools/llvm-snippy/include/snippy/Generator/SimRunner.h index 23822a197cb3..53d0f45251c9 100644 --- a/llvm/tools/llvm-snippy/include/snippy/Generator/SimRunner.h +++ b/llvm/tools/llvm-snippy/include/snippy/Generator/SimRunner.h @@ -42,20 +42,9 @@ class SimRunner { // Preform co-simulation run. // Each interpreter state will be reset before run. - void run(StringRef Programm, const IRegisterState &InitialRegState, - ProgramCounterType StartPC); - - // Adds output section name to the sim config - // in order to load it later to the model before execution. - void addNewEnvSection(const std::string &NewSectOutputName) { - auto &AdditionalSectionsNames = Env->SimCfg.AdditionalSectionsNames; - if (std::count(AdditionalSectionsNames.begin(), - AdditionalSectionsNames.end(), NewSectOutputName) != 0) - snippy::fatal(formatv("Section {0} has already been added to sim env.", - NewSectOutputName)); - AdditionalSectionsNames.push_back(NewSectOutputName); - } - + void run(const IRegisterState &InitialRegState, ProgramCounterType StartPC); + // Loads image of program into each interpreter. + void loadElf(StringRef Image); auto &getSimConfig() & { assert(Env); return Env->SimCfg; diff --git a/llvm/tools/llvm-snippy/include/snippy/Simulator/Simulator.h b/llvm/tools/llvm-snippy/include/snippy/Simulator/Simulator.h index 7dfa6780d78c..7254ec361bad 100644 --- a/llvm/tools/llvm-snippy/include/snippy/Simulator/Simulator.h +++ b/llvm/tools/llvm-snippy/include/snippy/Simulator/Simulator.h @@ -53,19 +53,7 @@ struct SimulationConfig { ProgramCounterType Size = 0; std::string Name; }; - std::vector
ProgSections; - - ProgramCounterType RomStart = 0; - ProgramCounterType RomSize = 0; - std::string RomSectionName; - - // Additional sections are the sections that need to be loaded in model - // e.g. RW sections filled with constants should be loaded to the model - // (these are mangled names) - std::vector AdditionalSectionsNames; - - ProgramCounterType RamStart = 0; - ProgramCounterType RamSize = 0; + std::vector
MemoryRegions; std::string TraceLogPath; }; @@ -130,4 +118,10 @@ template <> struct yaml::MappingTraits { static void mapping(yaml::IO &IO, snippy::SimulationConfig &Cfg); }; +template <> struct yaml::MappingTraits { + static void mapping(yaml::IO &IO, snippy::SimulationConfig::Section &S); +}; } // namespace llvm + +LLVM_SNIPPY_YAML_IS_SEQUENCE_ELEMENT(llvm::snippy::SimulationConfig::Section, + /* flow */ false); diff --git a/llvm/tools/llvm-snippy/include/snippy/Support/DiagnosticInfo.h b/llvm/tools/llvm-snippy/include/snippy/Support/DiagnosticInfo.h index dd0064eba8f8..680fb56fbdee 100644 --- a/llvm/tools/llvm-snippy/include/snippy/Support/DiagnosticInfo.h +++ b/llvm/tools/llvm-snippy/include/snippy/Support/DiagnosticInfo.h @@ -39,6 +39,7 @@ enum class WarningName { TooFarMaxPCDist, ModelException, UnusedSection, + EmptyElfSection, GenPlanVerification, SeedNotSpecified, }; diff --git a/llvm/tools/llvm-snippy/lib/Generator/Interpreter.cpp b/llvm/tools/llvm-snippy/lib/Generator/Interpreter.cpp index 767a63c6e02f..039e73645b4e 100644 --- a/llvm/tools/llvm-snippy/lib/Generator/Interpreter.cpp +++ b/llvm/tools/llvm-snippy/lib/Generator/Interpreter.cpp @@ -70,55 +70,21 @@ static std::unique_ptr makeObjectFile(MemoryBufferRef Buf) { return std::move(Exp.get()); } -static auto getSectionIt(object::ObjectFile &Obj, StringRef SectionName) { - auto SecIt = std::find_if(Obj.section_begin(), Obj.section_end(), - [&SectionName](const auto &S) { - auto Exp = S.getName(); - if (!Exp) - return false; - return Exp.get() == SectionName; - }); - return SecIt; -} - -static bool hasSection(object::ObjectFile &Obj, StringRef SectionName) { - return getSectionIt(Obj, SectionName) != Obj.section_end(); -} - -static StringRef getSectionData(object::ObjectFile &Obj, - StringRef SectionName) { - auto SectionIt = getSectionIt(Obj, SectionName); - assert(SectionIt != Obj.section_end()); - - auto Exp = SectionIt->getContents(); - if (!Exp) - snippy::fatal(SectionName + " section is empty"); - return Exp.get(); -} - -static auto getSectionLA(object::ObjectFile &Obj, StringRef SectionName) { - auto SectionIt = getSectionIt(Obj, SectionName); - assert(SectionIt != Obj.section_end()); - return SectionIt->getAddress(); -} - } // namespace llvm namespace llvm { namespace snippy { namespace { -void applyMemCfgToSimCfg(const MemoryConfig &MemCfg, SimulationConfig &SimCfg) { - llvm::transform(MemCfg.ProgSections, std::back_inserter(SimCfg.ProgSections), - [](auto &Section) { - return SimulationConfig::Section{ - Section.Start, Section.Size, Section.Name}; +void applyMemCfgToSimCfg(const Linker &L, SimulationEnvironment &Env) { + llvm::transform(L.sections(), std::back_inserter(Env.SimCfg.MemoryRegions), + [](auto &SE) { + auto &OutS = SE.OutputSection; + return SimulationConfig::Section{OutS.Desc.VMA, + OutS.Desc.Size, OutS.Name}; }); - SimCfg.RomStart = MemCfg.Rom.Start; - SimCfg.RomSize = MemCfg.Rom.Size; - SimCfg.RomSectionName = MemCfg.Rom.Name; - SimCfg.RamStart = MemCfg.Ram.Start; - SimCfg.RamSize = MemCfg.Ram.Size; + llvm::transform(L.sections(), std::back_inserter(Env.Sections), + [](auto &SE) { return SE.OutputSection.Desc; }); } } // namespace @@ -178,8 +144,7 @@ static void writeSectionToFile(ArrayRef Data, SimulationEnvironment Interpreter::createSimulationEnvironment( SnippyProgramContext &SPC, const TargetSubtargetInfo &ST, - const GeneratorSettings &Settings, const MemoryConfig &MemCfg, - TargetGenContextInterface &TgtCtx) { + const GeneratorSettings &Settings, TargetGenContextInterface &TgtCtx) { auto &State = SPC.getLLVMState(); const auto &SnippyTGT = State.getSnippyTarget(); @@ -190,10 +155,7 @@ SimulationEnvironment Interpreter::createSimulationEnvironment( Env.SnippyTGT = &SnippyTGT; Env.ST = &ST; - applyMemCfgToSimCfg(MemCfg, Env.SimCfg); - std::transform(L.sections().begin(), L.sections().end(), - std::back_inserter(Env.Sections), - [](auto &SE) { return SE.OutputSection.Desc; }); + applyMemCfgToSimCfg(L, Env); Env.SimCfg.TraceLogPath = TraceLogPath.getValue(); Env.TgtGenCtx = &TgtCtx; @@ -230,14 +192,14 @@ bool Interpreter::compareStates(const Interpreter &Another, if (!CheckMemory) return true; - std::vector MI1, MI2; - - MI1.resize(getRamSize()); - MI2.resize(getRamSize()); - - Simulator->readMem(getRamStart(), MI1); - Another.Simulator->readMem(getRamStart(), MI2); - return MI1 == MI2; + return llvm::all_of(Env.SimCfg.MemoryRegions, [&](auto &Region) { + std::vector MI1, MI2; + MI1.resize(Region.Size); + MI2.resize(Region.Size); + Simulator->readMem(Region.Start, MI1); + Another.Simulator->readMem(Region.Start, MI2); + return MI1 == MI2; + }); } bool Interpreter::endOfProg() const { @@ -246,14 +208,10 @@ bool Interpreter::endOfProg() const { void Interpreter::resetMem() { const auto &SimCfg = Env.SimCfg; - std::vector RAMZeroMem(SimCfg.RamSize, 0); - std::vector ROMZeroMem(SimCfg.RomSize, 0); - - Simulator->writeMem(SimCfg.RamStart, RAMZeroMem); - Simulator->writeMem(SimCfg.RomStart, ROMZeroMem); - for (auto &Section : SimCfg.ProgSections) { - std::vector ProgZeroMem(Section.Size, 0); - Simulator->writeMem(Section.Start, ProgZeroMem); + std::vector Zeros; + for (auto &&Region : SimCfg.MemoryRegions) { + Zeros.resize(Region.Size, 0); + Simulator->writeMem(Region.Start, Zeros); } } @@ -290,12 +248,51 @@ void Interpreter::reportSimulationFatalError(StringRef PrefixMessage) const { snippy::fatal(ErrorMessage.c_str()); } +bool Interpreter::coveredByMemoryRegion(MemAddr Start, MemAddr Size) const { + auto IsInsideOf = [&](auto &&Reg) { + return Reg.Start <= Start && Reg.Start + Reg.Size >= Start + Size; + }; + return llvm::any_of(Env.SimCfg.MemoryRegions, IsInsideOf); +} + +static StringRef getSectionName(llvm::object::SectionRef S) { + if (auto EName = S.getName()) + return *EName; + else + return ""; +} void Interpreter::loadElfImage(StringRef ElfImage) { std::string ProgramText; auto MemBuff = MemoryBuffer::getMemBuffer(ElfImage, "", false); auto ObjectFile = makeObjectFile(*MemBuff); - + // FIXME: we need to provide more context to error message. + // (at least elf name) + if (ObjectFile->isRelocatableObject()) + snippy::fatal("Trying to load relocatable object into model"); + for (auto &&Section : ObjectFile->sections()) { + if (!Section.isText() && !Section.isData() && !Section.isBSS()) + continue; + auto Address = Section.getAddress(); + auto Size = Section.getSize(); + if (!coveredByMemoryRegion(Address, Size)) + snippy::fatal( + formatv("Trying to load/allocate section '{0}' at address 0x{1:x} of " + "size 0x{2:x} which is not covered by model memory region", + getSectionName(Section), Address, Size)); + if (Section.isText() || Section.isData()) { + if (auto EContents = Section.getContents()) + Simulator->writeMem(Address, *EContents); + else + snippy::warn( + WarningName::EmptyElfSection, + formatv("ignored LOAD section '{0}'", getSectionName(Section)), + "empty contents"); + } else if (Section.isBSS()) { + std::vector Zeroes(Size, 0); + Simulator->writeMem(Address, Zeroes); + } + } auto EndOfProgSym = llvm::find_if(ObjectFile->symbols(), [](auto &Sym) { auto EName = Sym.getName(); return EName && EName.get() == Linker::getExitSymbolName(); @@ -306,34 +303,6 @@ void Interpreter::loadElfImage(StringRef ElfImage) { auto EAddress = EndOfProgSym->getAddress(); assert(EAddress && "Expected the address of symbol to be known"); ProgEnd = EAddress.get(); - - for (auto &ProgSection : Env.SimCfg.ProgSections) { - assert(hasSection(*ObjectFile, ProgSection.Name)); - - ProgramText = getSectionData(*ObjectFile, ProgSection.Name); - - if (ProgSection.Size < ProgramText.size()) - snippy::fatal(formatv("RX section '{0}' failed to fit code mapped to it: " - "section size is {1} and code size is {2}", - ProgSection.Name, ProgSection.Size, - ProgramText.size())); - Simulator->writeMem(ProgSection.Start, ProgramText); - } - if (!Env.SimCfg.RomSectionName.empty()) { - auto RODataName = Env.SimCfg.RomSectionName; - // Elf image might not have this section if - // .rodata happens to be empty. - if (hasSection(*ObjectFile, RODataName)) { - auto SnippyData = getSectionData(*ObjectFile, RODataName); - Simulator->writeMem(getSectionLA(*ObjectFile, RODataName), SnippyData); - } - } - - // adding sections with non-zero data - for (auto &It : Env.SimCfg.AdditionalSectionsNames) { - auto Data = getSectionData(*ObjectFile, It); - Simulator->writeMem(getSectionLA(*ObjectFile, It), Data); - } } void Interpreter::addInstr(const MachineInstr &MI, const LLVMState &State) { @@ -424,12 +393,7 @@ void Interpreter::initTransactionMechanism() { Env.CallbackHandler->getObserverByHandle(*TransactionsObserverHandle); assert(Transactions.empty()); - SmallVector, 3> MemoryConfig = { - std::pair{getRomStart(), getRomSize()}, - std::pair{getRamStart(), getRamSize()}}; - for (auto &Section : Env.SimCfg.ProgSections) - MemoryConfig.emplace_back(std::make_pair(Section.Start, Section.Size)); - for (auto [Start, Size] : MemoryConfig) { + for (auto [Start, Size, _] : Env.SimCfg.MemoryRegions) { if (Size == 0) continue; std::vector Snapshot(Size); diff --git a/llvm/tools/llvm-snippy/lib/Generator/SimRunner.cpp b/llvm/tools/llvm-snippy/lib/Generator/SimRunner.cpp index af8df2f12a0a..681088ea596b 100644 --- a/llvm/tools/llvm-snippy/lib/Generator/SimRunner.cpp +++ b/llvm/tools/llvm-snippy/lib/Generator/SimRunner.cpp @@ -11,33 +11,6 @@ namespace llvm { namespace snippy { -namespace { -Expected getAddressOfSymbolInImage(StringRef Image, - StringRef SymbolName) { - auto MemBuf = MemoryBuffer::getMemBuffer(Image, "", false); - - auto &&Bin = object::ObjectFile::createObjectFile(*MemBuf); - if (!Bin) - return Bin.takeError(); - auto &&Obj = *Bin; - - auto ExitSimIt = std::find_if(Obj->symbols().begin(), Obj->symbols().end(), - [SymbolName](const auto &Sym) { - if (auto Name = Sym.getName()) - return *Name == SymbolName; - return false; - }); - if (ExitSimIt == Obj->symbols().end()) - return {make_error(Twine("no symbol ") + Twine(SymbolName) + - Twine(" in image"))}; - - auto ExpectedAddress = ExitSimIt->getAddress(); - if (!ExpectedAddress) - return ExpectedAddress.takeError(); - - return *ExpectedAddress; -} -} // namespace SimRunner::SimRunner(LLVMContext &Ctx, const SnippyTarget &TGT, const TargetSubtargetInfo &Subtarget, @@ -61,18 +34,16 @@ SimRunner::SimRunner(LLVMContext &Ctx, const SnippyTarget &TGT, } } -void SimRunner::run(StringRef Program, const IRegisterState &InitialRegState, +void SimRunner::loadElf(StringRef Image) { + for (auto &I : CoInterp) + I->loadElfImage(Image); +} +void SimRunner::run(const IRegisterState &InitialRegState, ProgramCounterType StartPC) { - auto StopPC = getAddressOfSymbolInImage(Program, Linker::getExitSymbolName()); - if (auto E = StopPC.takeError()) { - auto Err = toString(std::move(E)); - snippy::fatal("[Internal error]: unable to get last instruction PC: " + - Twine(Err) + Twine("\nPlease, report a bug")); - } + for (auto &I : CoInterp) { I->setInitialState(InitialRegState); - I->loadElfImage(Program); - I->setStopModeByPC(*StopPC); + I->setStopModeByPC(I->getProgEnd()); I->setPC(StartPC); } diff --git a/llvm/tools/llvm-snippy/lib/Generator/SimulatorContextWrapperPass.cpp b/llvm/tools/llvm-snippy/lib/Generator/SimulatorContextWrapperPass.cpp index e97ccc20822a..4228f9eb66d2 100644 --- a/llvm/tools/llvm-snippy/lib/Generator/SimulatorContextWrapperPass.cpp +++ b/llvm/tools/llvm-snippy/lib/Generator/SimulatorContextWrapperPass.cpp @@ -37,10 +37,9 @@ void OwningSimulatorContext::initialize(SnippyProgramContext &ProgCtx, auto &ModelLibList = Settings.ModelPluginConfig.ModelLibraries; if (ModelLibList.empty()) return nullptr; - auto MemCfg = MemoryConfig::getMemoryConfig(Linker, GCFI); - auto Env = Interpreter::createSimulationEnvironment( - ProgCtx, SubTgt, Settings, MemCfg, TargetCtx); + auto Env = Interpreter::createSimulationEnvironment(ProgCtx, SubTgt, + Settings, TargetCtx); return std::make_unique(State.getCtx(), SnippyTgt, SubTgt, std::move(Env), ModelLibList); @@ -223,8 +222,9 @@ void SimulatorContext::runSimulator(const RunInfo &RI) { } auto &SimRunner = getSimRunner(); + SimRunner.loadElf(ImageToRun); - SimRunner.run(ImageToRun, InitRegState, StartPC); + SimRunner.run(InitRegState, StartPC); I.dumpCurrentRegState(FinalStateOutputYaml); auto RangesToDump = getMemoryRangesToDump(I, DumpMemorySection); diff --git a/llvm/tools/llvm-snippy/lib/Simulator/RISCVSimulator.cpp b/llvm/tools/llvm-snippy/lib/Simulator/RISCVSimulator.cpp index 0c8f4f8d1fab..0c66b7716d85 100644 --- a/llvm/tools/llvm-snippy/lib/Simulator/RISCVSimulator.cpp +++ b/llvm/tools/llvm-snippy/lib/Simulator/RISCVSimulator.cpp @@ -546,19 +546,6 @@ std::unique_ptr createRISCVSimulator( unsigned VLENB, bool EnableMisalignedAccess) { const auto &VTable = getSimulatorEntryPoint(ModelLib); - assert(!Cfg.ProgSections.empty()); - auto Starts = - llvm::map_range(Cfg.ProgSections, [](auto &S) { return S.Start; }); - auto Ends = llvm::map_range(Cfg.ProgSections, - [](auto &S) { return S.Start + S.Size; }); - auto FirstSection = std::min_element(Starts.begin(), Starts.end()); - auto LastSection = std::max_element(Ends.begin(), Ends.end()); - auto RomStart = FirstSection == Starts.end() - ? Cfg.RomStart - : std::min(Cfg.RomStart, *FirstSection); - auto CfgRomEnd = Cfg.RomStart + Cfg.RomSize; - auto RomEnd = - LastSection == Ends.end() ? CfgRomEnd : std::max(CfgRomEnd, *LastSection); auto SimInfo = deriveSimulatorIsaInfo(Subtarget); LLVM_DEBUG(dbgs() << "Model::isa_string: " << rvm::create_isa_string(SimInfo.Ext, SimInfo.Is64Bit) @@ -569,11 +556,14 @@ std::unique_ptr createRISCVSimulator( if (EnableMisalignedAccess) StateBuilder.enableMisalignedAccess(); - StateBuilder.setRomStart(RomStart); - StateBuilder.setRomSize(RomEnd - RomStart); - - StateBuilder.setRamStart(Cfg.RamStart); - StateBuilder.setRamSize(Cfg.RamSize); + // For legacy reasons, we allow to configure zero-size + // regions. However model implementation is allowed to raise + // an error for such regions, so filter them out here. + auto NonEmptyRegions = llvm::make_filter_range( + Cfg.MemoryRegions, [](auto &&Region) { return Region.Size; }); + for (auto &&Region : NonEmptyRegions) + StateBuilder.addMemoryRegion(Region.Start, Region.Size, + Region.Name.c_str()); if (SimInfo.Is64Bit) StateBuilder.setRV64Isa(); diff --git a/llvm/tools/llvm-snippy/lib/Simulator/Simulator.cpp b/llvm/tools/llvm-snippy/lib/Simulator/Simulator.cpp index acbc24e37a56..1436d5f8920e 100644 --- a/llvm/tools/llvm-snippy/lib/Simulator/Simulator.cpp +++ b/llvm/tools/llvm-snippy/lib/Simulator/Simulator.cpp @@ -12,18 +12,82 @@ namespace llvm { +namespace { + +struct RegionKey { + const char *Name; + const char *KeyStart; + const char *KeySize; +}; + +// legacy named region mapping info. +constexpr std::array RegionKeys{ +// clang-format off +#ifdef SNIPPY_REGION_KEY +#error "SNIPPY_REGION_KEY" should not be defined here +#endif +#define SNIPPY_REGION_KEY(X) \ + RegionKey { X, X "_start", X "_size" } + SNIPPY_REGION_KEY("prog"), SNIPPY_REGION_KEY("rom"), + SNIPPY_REGION_KEY("ram"), +#undef SNIPPY_REGION_KEY + // clang-format on +}; + +} // namespace + +void yaml::MappingTraits::mapping( + yaml::IO &IO, snippy::SimulationConfig::Section &S) { + IO.mapRequired("start", S.Start); + IO.mapRequired("size", S.Size); + IO.mapRequired("name", S.Name); +} + void yaml::MappingTraits::mapping( yaml::IO &IO, snippy::SimulationConfig &Cfg) { - auto &ProgSection = Cfg.ProgSections.empty() ? Cfg.ProgSections.emplace_back() - : Cfg.ProgSections.front(); - IO.mapRequired("prog_start", ProgSection.Start); - IO.mapRequired("prog_size", ProgSection.Size); - IO.mapRequired("rom_start", Cfg.RomStart); - IO.mapRequired("rom_size", Cfg.RomSize); - IO.mapRequired("ram_start", Cfg.RamStart); - IO.mapRequired("ram_size", Cfg.RamSize); - IO.mapOptional("prog_section", ProgSection.Name); - IO.mapOptional("rom_section", Cfg.RomSectionName); + if (!IO.outputting()) { + std::optional> RegionsOpt; + IO.mapOptional("memory", RegionsOpt); + if (RegionsOpt) { + Cfg.MemoryRegions = *RegionsOpt; + } else { + // For backward compatibility + Cfg.MemoryRegions.clear(); + + llvm::transform(RegionKeys, std::back_inserter(Cfg.MemoryRegions), + [&](auto &&MappingInfo) { + snippy::SimulationConfig::Section LegacySection{}; + IO.mapRequired(MappingInfo.KeyStart, + LegacySection.Start); + IO.mapRequired(MappingInfo.KeySize, LegacySection.Size); + LegacySection.Name = MappingInfo.Name; + return LegacySection; + }); + std::string Dummy; + IO.mapOptional("prog_section", Dummy); + IO.mapOptional("rom_section", Dummy); + } + } else { + std::array Regions; + llvm::transform(RegionKeys, Regions.begin(), [&](auto &&Keys) { + return llvm::find_if(Cfg.MemoryRegions, [&Keys](auto &&Region) { + return Region.Name == Keys.Name; + }); + }); + + if (llvm::all_of(Regions, [&](auto &&It) { + return It != Cfg.MemoryRegions.end(); + })) { + // legacy format + for (auto &&[Keys, RegionIt] : llvm::zip(RegionKeys, Regions)) { + IO.mapRequired(Keys.KeyStart, RegionIt->Start); + IO.mapRequired(Keys.KeySize, RegionIt->Size); + } + } else { + // new format + IO.mapRequired("memory", Cfg.MemoryRegions); + } + } IO.mapOptional("trace_log", Cfg.TraceLogPath); } diff --git a/llvm/tools/llvm-snippy/lib/Simulator/Transactions.cpp b/llvm/tools/llvm-snippy/lib/Simulator/Transactions.cpp index cb50f1169bd7..ce441dcd212d 100644 --- a/llvm/tools/llvm-snippy/lib/Simulator/Transactions.cpp +++ b/llvm/tools/llvm-snippy/lib/Simulator/Transactions.cpp @@ -100,7 +100,7 @@ char TransactionStack::getMemPrevValue( MemSnapshot.begin(), MemSnapshot.end(), [Addr](const auto &S) { auto Start = S.first; auto Size = S.second.size(); - return Start <= Addr && Addr <= Start + Size; + return Start <= Addr && (Addr < Start + Size || Start + Size == 0ull); }); assert(MemSnapshotIt != MemSnapshot.end() && "Memory snapshot must contain whole memory.");