Simulators van computersystemen: een bekende full-platform simulator en onbekende met de klok mee en sporen

In het tweede deel van het artikel over computersysteemsimulators zal ik in een eenvoudige inleidende vorm verder praten over computersimulators, namelijk over de volledige platformsimulatie, die de gemiddelde gebruiker het vaakst tegenkomt, evenals over de clock-by -klokmodel en sporen, die vaker voorkomen in ontwikkelaarskringen.

Simulators van computersystemen: een bekende full-platform simulator en onbekende met de klok mee en sporen

В het eerste deel Ik heb gesproken over wat simulatoren in het algemeen zijn, en over de simulatieniveaus. Op basis van die kennis stel ik voor om wat dieper te duiken en te praten over volledige platformsimulatie, hoe je sporen kunt verzamelen, wat je er later mee kunt doen, en over klok-voor-klok microarchitecturale emulatie.

Volledige platformsimulator, of “Alleen in het veld is geen krijger”

Als je de werking van één specifiek apparaat, bijvoorbeeld een netwerkkaart, wilt bestuderen, of firmware of een driver voor dit apparaat wilt schrijven, dan kan zo'n apparaat afzonderlijk worden gesimuleerd. Het is echter niet erg handig om het los van de rest van de infrastructuur te gebruiken. Om het bijbehorende stuurprogramma uit te voeren, hebt u een centrale processor, geheugen, toegang tot een databus, enz. nodig. Bovendien heeft het stuurprogramma een besturingssysteem (OS) en een netwerkstack nodig om te kunnen functioneren. Bovendien kan een aparte pakketgenerator en responsserver nodig zijn.

Een simulator op volledig platform creëert een omgeving voor het uitvoeren van een complete softwarestack, die alles omvat, van het BIOS en de bootloader tot het besturingssysteem zelf en de verschillende subsystemen ervan, zoals dezelfde netwerkstack, stuurprogramma's en applicaties op gebruikersniveau. Om dit te doen, implementeert het softwaremodellen van de meeste computerapparaten: processor en geheugen, schijf, invoer-/uitvoerapparaten (toetsenbord, muis, beeldscherm) en dezelfde netwerkkaart.

Hieronder ziet u een blokdiagram van de x58-chipset van Intel. Een computersimulator op volledig platform op deze chipset vereist de implementatie van de meeste van de genoemde apparaten, inclusief die in de IOH (Input/Output Hub) en ICH (Input/Output Controller Hub), die niet in detail worden weergegeven in het blokdiagram . Hoewel er, zoals de praktijk laat zien, niet veel apparaten zijn die niet worden gebruikt door de software die we gaan gebruiken. Er hoeven geen modellen van dergelijke apparaten te worden gemaakt.

Simulators van computersystemen: een bekende full-platform simulator en onbekende met de klok mee en sporen

Meestal worden simulatoren op het volledige platform geïmplementeerd op processorinstructieniveau (ISA, zie hieronder). vorig artikel). Hierdoor kunt u relatief snel en goedkoop de simulator zelf maken. Het ISA-niveau is ook goed omdat het min of meer constant blijft, in tegenstelling tot bijvoorbeeld het API/ABI-niveau, dat vaker verandert. Bovendien kunt u met implementatie op instructieniveau zogenaamde ongewijzigde binaire software uitvoeren, dat wil zeggen reeds gecompileerde code zonder enige wijzigingen uitvoeren, precies zoals deze op echte hardware wordt gebruikt. Met andere woorden, u kunt een kopie (“dump”) van uw harde schijf maken, deze specificeren als een afbeelding voor een model in een simulator op volledig platform, en voila! – Het besturingssysteem en andere programma's worden zonder extra acties in de simulator geladen.

Simulatieprestaties

Simulators van computersystemen: een bekende full-platform simulator en onbekende met de klok mee en sporen

Zoals zojuist hierboven vermeld, is het proces van het simuleren van het hele systeem, dat wil zeggen al zijn apparaten, een nogal trage onderneming. Als je dit alles ook op een heel gedetailleerd niveau implementeert, bijvoorbeeld microarchitectonisch of logisch, dan wordt de uitvoering extreem traag. Maar het instructieniveau is een geschikte keuze en zorgt ervoor dat het besturingssysteem en de programma's kunnen worden uitgevoerd met snelheden die voldoende zijn om de gebruiker er comfortabel mee te laten communiceren.

Hier zou het passend zijn om het onderwerp simulatorprestaties aan te raken. Het wordt meestal gemeten in IPS (instructies per seconde), preciezer gezegd in MIPS (miljoenen IPS), dat wil zeggen het aantal processorinstructies dat door de simulator in één seconde wordt uitgevoerd. Tegelijkertijd is de snelheid van de simulatie ook afhankelijk van de prestaties van het systeem waarop de simulatie zelf draait. Daarom is het misschien juister om te praten over de "vertraging" van de simulator in vergelijking met het oorspronkelijke systeem.

De meest voorkomende full-platformsimulators op de markt, zoals QEMU, VirtualBox of VmWare Workstation, presteren goed. Het is voor de gebruiker misschien niet eens merkbaar dat er in de simulator wordt gewerkt. Dit gebeurt dankzij de speciale virtualisatiemogelijkheden die zijn geïmplementeerd in processors, binaire vertaalalgoritmen en andere interessante dingen. Dit is allemaal een onderwerp voor een apart artikel, maar kort gezegd is virtualisatie een hardwarefunctie van moderne processors waarmee simulatoren geen instructies kunnen simuleren, maar deze rechtstreeks naar een echte processor kunnen sturen voor uitvoering, als de architecturen van de processor natuurlijk de simulator en de processor zijn vergelijkbaar. Binaire vertaling is de vertaling van gastmachinecode naar hostcode en daaropvolgende uitvoering op een echte processor. Hierdoor is de simulatie slechts iets langzamer, 5-10 keer, en draait deze vaak zelfs op dezelfde snelheid als het echte systeem. Hoewel dit door veel factoren wordt beïnvloed. Als we bijvoorbeeld een systeem met enkele tientallen processors willen simuleren, dan zal de snelheid onmiddellijk enkele tientallen keren dalen. Aan de andere kant ondersteunen simulators zoals Simics in de nieuwste versies hosthardware met meerdere processors en parallelliseren ze de gesimuleerde kernen effectief op de kernen van een echte processor.

Als we het hebben over de snelheid van microarchitecturale simulatie, dan is deze meestal enkele ordes van grootte, ongeveer 1000-10000 keer langzamer dan uitvoering op een gewone computer, zonder simulatie. En implementaties op het niveau van logische elementen zijn verschillende ordes van grootte langzamer. Daarom wordt op dit niveau een FPGA als emulator gebruikt, wat de prestaties aanzienlijk kan verbeteren.

De onderstaande grafiek toont bij benadering de afhankelijkheid van de simulatiesnelheid van modeldetails.

Simulators van computersystemen: een bekende full-platform simulator en onbekende met de klok mee en sporen

Beat-voor-beat simulatie

Ondanks hun lage uitvoeringssnelheid zijn microarchitecturale simulatoren vrij gebruikelijk. Simulatie van de interne blokken van de processor is noodzakelijk om de uitvoeringstijd van elke instructie nauwkeurig te simuleren. Er kan hier sprake zijn van misverstanden; waarom zou u immers niet eenvoudigweg de uitvoeringstijd voor elke instructie programmeren? Maar zo'n simulator zal zeer onnauwkeurig zijn, omdat de uitvoeringstijd van dezelfde instructie van oproep tot oproep kan verschillen.

Het eenvoudigste voorbeeld is een instructie voor geheugentoegang. Als de gevraagde geheugenlocatie beschikbaar is in de cache, zal de uitvoeringstijd minimaal zijn. Als deze informatie niet in de cache zit (“cache miss”), zal dit de uitvoeringstijd van de instructie aanzienlijk verlengen. Voor nauwkeurige simulatie is dus een cachemodel vereist. De kwestie beperkt zich echter niet tot het cachemodel. De processor wacht niet simpelweg tot gegevens uit het geheugen worden opgehaald als deze zich niet in de cache bevinden. In plaats daarvan zal het beginnen met het uitvoeren van de volgende instructies, waarbij de instructies worden gekozen die niet afhankelijk zijn van het resultaat van het lezen uit het geheugen. Dit is de zogenaamde “out of order” uitvoering (OOO, out of order executie), die nodig is om de inactieve tijd van de processor te minimaliseren. Het modelleren van de overeenkomstige processorblokken zal helpen om met dit alles rekening te houden bij het berekenen van de uitvoeringstijd van instructies. Onder deze instructies, die worden uitgevoerd terwijl op het resultaat van het lezen uit het geheugen wordt gewacht, kan een voorwaardelijke sprongoperatie plaatsvinden. Als het resultaat van de voorwaarde op dit moment onbekend is, stopt de processor de uitvoering niet, maar doet hij een "gok", voert hij de juiste vertakking uit en blijft hij proactief instructies uitvoeren vanaf het overgangspunt. Een dergelijk blok, een branch-voorspeller genoemd, moet ook in de microarchitectuursimulator worden geïmplementeerd.

De onderstaande afbeelding toont de hoofdblokken van de processor, het is niet nodig om deze te kennen, deze wordt alleen getoond om de complexiteit van de microarchitectuurimplementatie te tonen.

Simulators van computersystemen: een bekende full-platform simulator en onbekende met de klok mee en sporen

De werking van al deze blokken in een echte processor wordt gesynchroniseerd door speciale kloksignalen, en hetzelfde gebeurt in het model. Een dergelijke microarchitectuursimulator wordt cyclusnauwkeurig genoemd. Het belangrijkste doel ervan is het nauwkeurig voorspellen van de prestaties van de processor die wordt ontwikkeld en/of het berekenen van de uitvoeringstijd van een specifiek programma, bijvoorbeeld een benchmark. Als de waarden lager zijn dan vereist, zal het nodig zijn om de algoritmen en processorblokken aan te passen of het programma te optimaliseren.

Zoals hierboven weergegeven is klok-voor-klok-simulatie erg traag en wordt daarom alleen gebruikt bij het bestuderen van bepaalde momenten van de werking van een programma, waarbij het nodig is om de werkelijke snelheid van de programma-uitvoering te achterhalen en de toekomstige prestaties van het apparaat waarvan het programma wordt uitgevoerd te evalueren. prototype wordt gesimuleerd.

In dit geval wordt een functionele simulator gebruikt om de resterende looptijd van het programma te simuleren. Hoe gebeurt deze combinatie van gebruik in werkelijkheid? Eerst wordt de functionele simulator gelanceerd, waarop het besturingssysteem en alles wat nodig is om het onderzochte programma uit te voeren, worden geladen. We zijn tenslotte niet geïnteresseerd in het besturingssysteem zelf, noch in de beginfase van het starten van het programma, de configuratie ervan, enz. We kunnen deze delen echter ook niet overslaan en meteen vanuit het midden doorgaan met het uitvoeren van het programma. Daarom worden al deze voorbereidende stappen uitgevoerd op een functionele simulator. Nadat het programma is uitgevoerd tot het voor ons interessante moment zijn er twee opties mogelijk. U kunt het model vervangen door een klok-voor-cyclus-model en doorgaan met de uitvoering. De simulatiemodus die gebruikmaakt van uitvoerbare code (dat wil zeggen, reguliere gecompileerde programmabestanden) wordt uitvoeringsgestuurde simulatie genoemd. Dit is de meest voorkomende simulatieoptie. Een andere aanpak is ook mogelijk: trace-driven simulatie.

Trace-gebaseerde simulatie

Het bestaat uit twee stappen. Met behulp van een functionele simulator of op een echt systeem wordt een logboek van programmaacties verzameld en naar een bestand geschreven. Dit logboek wordt een trace genoemd. Afhankelijk van wat er wordt onderzocht, kan de tracering uitvoerbare instructies, geheugenadressen, poortnummers en interruptinformatie omvatten.

De volgende stap is het "afspelen" van de trace, wanneer de klok-voor-klok-simulator de trace leest en alle daarin geschreven instructies uitvoert. Uiteindelijk krijgen we de uitvoeringstijd van dit deel van het programma, evenals verschillende kenmerken van dit proces, bijvoorbeeld het percentage hits in de cache.

Een belangrijk kenmerk van het werken met sporen is determinisme, dat wil zeggen dat door de simulatie uit te voeren op de hierboven beschreven manier, we steeds opnieuw dezelfde reeks acties reproduceren. Dit maakt het mogelijk om, door modelparameters (cache-, buffer- en wachtrijgroottes) te wijzigen en verschillende interne algoritmen te gebruiken of deze af te stemmen, te bestuderen hoe een bepaalde parameter de systeemprestaties beïnvloedt en welke optie de beste resultaten geeft. Dit alles kan worden gedaan met een prototype-apparaatmodel voordat een daadwerkelijk hardware-prototype wordt gemaakt.

De complexiteit van deze aanpak ligt in de noodzaak om eerst de applicatie uit te voeren en de tracering te verzamelen, evenals de enorme omvang van het traceringsbestand. De voordelen omvatten het feit dat het voldoende is om alleen het deel van het apparaat of platform van belang te simuleren, terwijl voor simulatie door uitvoering doorgaans een compleet model vereist is.

In dit artikel hebben we dus gekeken naar de kenmerken van simulatie op het volledige platform, gesproken over de snelheid van implementaties op verschillende niveaus, klok-voor-cyclus-simulatie en sporen. In het volgende artikel zal ik de belangrijkste scenario's beschrijven voor het gebruik van simulatoren, zowel voor persoonlijke doeleinden als vanuit ontwikkelingsoogpunt in grote bedrijven.

Bron: www.habr.com

Voeg een reactie