Pipelining i RISC-processorn. Joakim Lindström Institutionen för informationsbehandling Åbo Akademi E-post: jolindst@abo.fi



Relevanta dokument
Datorsystem 2 CPU. Förra gången: Datorns historia Denna gång: Byggstenar i en dators arkitektur. Visning av Akka (för de som är intresserade)

Datorsystemteknik DVGA03 Föreläsning 8

SVAR TILL TENTAMEN I DATORSYSTEM, VT2013

Datorarkitekturer med operativsystem ERIK LARSSON

Pipelining i Intel Pentium II

Närliggande allokering Datorteknik

Datorarkitekturer med operativsystem ERIK LARSSON

Lunds Tekniska Högskola Datorarkitektur med operativsystem EITF60. Superscalar vs VLIW. Cornelia Kloth IDA2. Inlämningsdatum:

Grundläggande datavetenskap, 4p

DatorsystemteknikDAVA14 Föreläsning 9

Tentamen den 18 mars svar Datorteknik, EIT070

Digitala System: Datorteknik ERIK LARSSON

0.1. INTRODUKTION Instruktionens opcode decodas till en språknivå som är förstålig för ALUn.

Tentamen den 14 januari 2015 Datorarkitekturer med operativsystem, EDT621, 7,5 poäng

Digitala System: Datorteknik ERIK LARSSON

Datorteknik. Föreläsning 6. Processorns uppbyggnad, pipelining. Institutionen för elektro- och informationsteknologi, LTH. Mål

Hantering av hazards i pipelines

HF0010. Introduktionskurs i datateknik 1,5 hp

TSEA28 Datorteknik Y (och U)

Svar till tentamen den 16 december 2013 Datorarkitekturer med operativsystem, EDT621, 7,5 poäng

Moment 2 Digital elektronik. Föreläsning Inbyggda system, introduktion

Vad bör göras? Steg 1. RISC => pipelining. Parallellism. Pipelining. Nya LDA 13. RISC(reduced instruction set computer) Öka klockfrekvensen

Datorteknik ERIK LARSSON

TSEA28 Datorteknik Y (och U)

Datorteknik ERIK LARSSON

Exempeltentamen Datorteknik, EIT070,

Datorteknik. Tomas Nordström. Föreläsning 2. För utveckling av verksamhet, produkter och livskvalitet.

Grunderna i stegkodsprogrammering

Pipelining i Intel 80486

Datorteknik ERIK LARSSON

Datorsystemteknik DAV A14 Föreläsning 1

Arm Cortex-A8 Pipeline

Tentamen den 12 januari 2017 Datorarkitektur med operativsystem, EDT621

Hannes Larsson - IDA 2, LTH Campus Helsingborg. NEC V R 4300i. Interlock-handling EDT621

IBM POWER4, den första flerkärniga processorn och dess pipelines.

Datorarkitekturer med operativsystem ERIK LARSSON

Fetch-Execute. Datorteknik. Pipelining. Pipeline diagram (vid en viss tidpunkt)

Processor pipelining genom historien (Intel i9-intel i7)

Övning1 Datorteknik, HH vt12 - Talsystem, logik, minne, instruktioner, assembler

Tentamen den 14 januari 2016 Datorarkitektur med operativsystem, EDT621

LUNDS UNIVERSITET. Parallell exekvering av Float32 och INT32 operationer

Multi-ported cache En rapport om några lösningar till att få flera minnesaccesser simultant.

Hur det går att minska effektutvecklingen i en processor genom att ändra pipeline

Minnet från processorns sida Datorteknik

F2: Motorola Arkitektur. Assembler vs. Maskinkod Exekvering av instruktioner i Instruktionsformat MOVE instruktionen

4. Pipelining. 4. Pipelining

Datorarkitekturer med operativsystem ERIK LARSSON

Föreläsningsanteckningar 4. Pipelining

En Von Neumann-arkitektur ( Von Neumann-principen i föreläsning 1) innebär:

Datormodell. Datorns uppgifter -Utföra program (instruktioner) Göra beräkningar på data Flytta data Interagera med omvärlden

System S. Datorarkitektur - en inledning. Organisation av datorsystem: olika abstraktionsnivåer. den mest abstrakta synen på systemet

Tentamen den 17 mars 2016 Datorteknik, EIT070

Spekulativ exekvering i CPU pipelining

Pipeline hos ARM Cortex-A53 och ARM Cortex-A73

Elektroteknik MF1016 föreläsning 9 MF1017 föreläsning 7 Mikrodatorteknik

Parallellism i CDC 7600, pipelinens ursprung

Datorarkitektur. Fö 9: Datorarkitektur. Datororganisation. Typiska Arkitekturattribut. Introduktion till datorarkitektur.

Det finns en hemsida. Adressen är

SIMD i Intel s P5- baserade Pentium MMX

Datorarkitektur I. Tentamen Lördag 10 April Ekonomikum, B:154, klockan 09:00 14:00. Följande gäller: Skrivningstid: Fråga

DEC Alpha instruktions Arkitektur

CDC en jämförelse mellan superskalära processorer. EDT621 Campus Helsingborg av: Marcus Karlsson IDA

32 Bitar Blir 64 Sammanfattning

Datorarkitekturer med operativsystem ERIK LARSSON

Föreläsningsanteckningar 2. Mikroprogrammering I

En något mer detaljerad bild av en processor. De tre delarna i processorn är: Nere 3ll vänster finns e' antal register som används för a' lagra data.

En något mer detaljerad bild av en processor. De tre delarna i processorn är: Nere 3ll vänster finns e' antal register som används för a' lagra data.

Program Datorteknik. Kontrollenhet. Exekvering av en instruktion. Abstraktionsnivå: Högnivåspråk. Assemblyspråk. Maskinspråk.

Datorteknik ERIK LARSSON

Superscalar Bra: Hårdvaran löser allt: Hårdvara detekterar poten6ell parallellism av instruk6oner Hårdvara försöker starta exekvering (issue) av så

LABORATION DATORTEKNIK D. Pipelining. Namn och personnummer. Version: (OS,OVA,AN)

Hantering av hazards i multi-pipelines

Tentamen den 9 januari 2018 Datorarkitekturer med operativsystem (EITF60)

Institutionen för datavetenskap 2014/15

Läsminne Read Only Memory ROM

Parallellism i NVIDIAs Fermi GPU

Föreläsning 3.1: Datastrukturer, en översikt

Tentamen i Digitala system - EDI610 15hp varav denna tentamen 4,5hp

Datorsystem. Tentamen

Datorsystem. Exempeltentamen

Komma över Memory wall med 3D stacked minne LTH Ingenjörshögskolan vid Campus Helsingborg Institutionen för datavetenskap

TSEA28 Datorteknik Y (och U)

Emil Kristiansson Kurs: EDT621 Delmoment: Rapport. En introduktion till Smart cache

Datorsystem. Tentamen

Utvecklingen från en 8 bitars till en 16 bitars mikroprocessor

MESI i Intel Core 2 Duo

Tentamen Datorteknik D del 2, TSEA49

Datorhistorik. Föreläsning 3 Datorns hårdvara EDSAC. Eniac. I think there is a world market for maybe five computers. Thomas Watson, IBM, 1943

Objektorienterad programmering

Digitalteknik och Datorarkitektur 5hp

Programmerbar logik. Kapitel 4

Intel Pentium. Intel khz. 32 million 2600MHz. Copyright 2005 Benny Thörnberg, Mattias O Nils

Målsättning med kursen

Hyper Threading Intels implementation av SMT. Datorarkitekturer med operativsystem - EITF60. Felix Danielsson IDA2

Cacheminne i en Intel Core 2 Duo-processor

Datorarkitekturer med Operativsystem

TSEA28 Datorteknik Y (och U)

SVAR TILL TENTAMEN I DATORSYSTEM, HT2013

MIKRODATORTEKNIK 2012 INNEHÅLLSFÖRTECKNING

Digital- och datorteknik

Transkript:

Pipelining i RISC-processorn Joakim Lindström Institutionen för informationsbehandling Åbo Akademi E-post: jolindst@abo.fi

Innehållsförteckning 1. Inledning 2. Historia: Intel 8086 (1978) till Pentium 4 (2000) 3. Principer för RISC-arkitektur 4. Effektiviseringsmetoder. 4.1 Pipelining 4.2 Pipelining av funktionella enheter 4.3 Dynamisk exekvering (Dynamic execution) 4.4 Branch prediction 5. IA-32 arkitekturen 5.1 Instruktionsuppsättning och assemblerprogrammering 5.2 Mikroarkitekturen 5.3 Pipelinen i Pentium 4 6. Avslutning Abstrakt Den explosiva utvecklingen av integrerade kretsar har lett till dagens effektiva processorer. Enligt Moores lag kommer antalet transistorer som ryms på en krets att fördubblas var 18:e månad. Detta möjliggör att man kan konstruera mer avancerade processorer. Orsaken till dagens snabba processorer är inte endast högre klockfrekvenser utan även mer utvecklade och optimerade processorarkitekturer och effektiviseringsmetoder. Sådana metoder är: Pipelining; flera instruktioner utförs parallellt och ökar genomloppet av instruktioner i processorn, branch prediction; löser datakonflikter i pipelinen, out-of-order execution eller dynamisk exekvering; omorganisera instruktioner för att lösa datakonflikter. De flesta moderna processorer är RISC-processorer för ökad prestanda, vilket betyder att det finns ett relativt litet antal (enkla)instruktioner. Trots detta kan det för assemblerprogrammeraren se ut som om det skulle finnas ett stort antal instruktioner. Detta beror på att mikroarkitekturen översätter dessa instruktioner till RISC-instruktioner, så kallad mikrokod (microcode). 1

1. Inledning Inom de närmaste 20 åren har det gått mycket framåt inom processorutvecklingen. Processorerna har blivit mycket snabbare vilket här märkts i det allt bredare användningsområdet för persondatorer. Datorerna har blivit bättre på att hantera bild, ljud och datorgrafik. Men megahertz racet har en aning avstannat verkar det som. Klockfrekvenserna har inte ökat i samma rasande takt som de gjorde för några år sedan. Istället har processortillverkarna satsat på att utveckla processorer som kan göra fler saker parallellt. Att göra två saker samtidigt men på halva hastigheten ger ju samma resultat. I vissa fall har t.o.m. klockfrekvenserna sjunkit. Denna uppsats handlar om dessa metoder för parallellitet. Hur man kan göra fler saker samtidigt på en uppsättning hårdvara. Dessa metoder leder även till en hel del problem av olika slag som måste beaktas. Jag kommer att ta upp en hel del historik. Hur det har varit tidigare och hur datorerna har förändrats. 2. Historia: Intel 8086 (1978) till Pentium 4 (2004) Intels processorer är bakåtkompatibla. Objektkod från 1978 kan fortfarande köras på de senaste processorerna i IA-32 arkitekturen. IA-32 arkitekturens föregångare är 16-bits processorer. Sådana processorer är 8086 och 8088 som båda kom 1978. 8086 hade 16-bits register, 16 bits extern databuss och en 20 bits adressering vilket gav 1 MB RAM. 8088 var liknande som 8086 förutom att den hade en 8 bits databuss istället för 16 bitars. Intel 80286 som kom 1982 var även den en 16 bits processor. Det nya med 80286 var minneshanteringen. Den hade protected mode för minnet. En funktion som använder en basaddress (base address) och en gränsadress (limit adress) för att förhindra programmet att gå utanför sitt eget minnesområde. 80286 använde en 24 bits basadress, vilket gav 16 Mbyte minnesrymd. Intel 80386 processorn, som kom 1985 var den första 32 bits processorn i familjen. Den hade 32 bits register för både operander och adresser precis som många 2

av dagens processorer har. Den första halvan av de 32 bitarna motsvarar de 16 bitarna i de tidigare arkitekturerna. På så vis är processorerna bakåtkompatibla. 32 bitar ger en minnerymd på 4 GB vilket fortfarande gäller för dagens 32 bits processorer. 80386 gav även virtuellt minne och sidbyten (paging) på 4 KB stora sidor. 386 gav även en del parallellitet i exekveringen av instruktionerna. 80486 processorn som kom 1989 gav stöd för utökad parallellitet. Den hade en 5 stegs pipeline som kunde ha maximalt 5 instruktioner i exekvering samtidigt. Utöver detta hade den ett 8 KB cacheminne integrerat i processorn. 1993 kom den första Pentium processorn. Parallelliteten utökades ytterligare genom att en extra pipeline. Den hade 2 pipelines som kallades för u och v och gjorde att 2 instruktioner kunde exekveras för varje klockcykel. Det integrerade cacheminnet utökades från till det dubbla jämfört 80846. Pentium hade två 4 Kbyte cacheminnen, en för programkod och en för data. Dessutom kom branch prediction med en hopptabell (branch table) som var integrerad på kretsen [IA32IntMan]. 1997 var det dags att utöka Pentium processorerna med MMX multimedia extensioner. Där tillkom 57 nya instruktioner som använde flyttalsstacken för att accelerera multimedia och kommunikations applikationer. MMX arbetar på många korta dataelement. Metoden kallas single instruktion, multiple data (SIMD). Alltså multipla dataelement i en enda instruktion [HenPat2005]. Pentium II och Pentium III processorn tillhör P6 mikroarkitekturfamiljen (1995-1999). Pentium II ökade storleken av cacheminnet till 16 KB för nivå 1 cache och 265 för nivå 2 [IA32IntMan]. Pentium III introducerade nya multimediaextensioner: dataström SIMD (data stream SIMD). Skillnaden var 8 nya register dubbelt så breda (128 bit), så att fyra 32 bits flyttalsinstruktioner kunde utföras parallellt. För förbättrad minnesprestanda SSE inkluderade streaming store (dataström sparning) som kunde förbikoppla cache minnena och skriva direkt till RAM [HenPat2005]. År 2000 kom den senaste och nuvarande Pentium 4 processor familjen som bygger på NetBurst arkitekturen. Pentium 4 introducerade SSE2 som är en förbättrad variant av SSE, och introducerade även Hyper Threading teknologin, som är en funktion som ger en illusion av två logiska processorer. Detta för att kunna utnyttja alla 3

funktionella enheter bättre.[ia32intman] Det nya med SSE2 var att den kunde hantera en ny datatyp: dubbel precision flyttal, alltså 64 bit. Med SSE2 kan man göra par av dubbel precision flyttalsoperationer parallellt. Nästan alla av de 144 instruktionerna är varianter ar av gamla SSE instruktioner som opererar på 64 bits flyttal [HenPat2005]. 3. Principer för RISC-arkitektur RISC (reduced instruction set) processorer är vad som används i dagens desktop datorer. Tidigare användes CISC (complex instruction set computer). CISC karakteriseras av ett stort antal instruktioner som processorn kan exekvera. Dessa syns om man tittar på assemblerspråket för processorn. Instruktionerna består av kraftfulla konstruktioner som liknar satser i ett högnivå språk som t.ex. C eller FORTRAN. Principen med CISC är att: Gör inte i mjukvara vad du kan göra direkt i hårdvaran. RISC arkitekturerna däremot består av enkla instruktioner som är betydligt enklare är instruktionerna i ett högnivåspråk. Det kommer att ta flera RISCinstruktioner att göra samma sak än det tar CISC-instruktioner. Men det går snabbare att utföra RISC-instruktionerna. RISC konceptet är egentligen inte något nytt. Det fans maskiner redan på 60- och 70-talet som hade RISC, men det var först på 80-talet som tekniken hade gått så mycket framåt att RISC utgjorde något ordentligt alternativ till CISC. PÅ den tiden fanns en debatt huruvida det var RISC eller CISC som gällde. Idag är det dock klart att RISC- arkitekturer är den som ger mest fördelar. Man kan ju undra: om RISC är så mycket snabbare varför använde man överhuvudtaget CISC maskiner? Svaret till det är att med den tidens teknik så var CISC en bättre väg att gå. För det första så var inte kompilatorerna lika väl utvecklade som de är idag. Det fanns kompilatorer men de gav inte någon speciellt optimal kod och slösade med minne. Därför var det viktigt för programmerare att känna till assemblerspråket. Ett kraftfullt assemblerspråk var användbart och gjorde programmerarens arbete enklare, 4

men det fanns också andra fördelar. Kraftfulla instruktioner sparade minne och tid vid exekveringen. En annan sak var att datorer på den tiden hade mycket begränsat minnesutrymme. Därför var det bra att ha instruktioner som gjorde så mycket som möjligt med en enda instruktion. Vissa av gamla tidens datorer kunde ha en instruktion som gjorde en slinga (loop) i bara en enda maskininstruktion. Desto mindre utrymme själva programkoden tog upp desto mer fanns det tillgängligt för data. En annan sak var att minnen dessutom var väldigt långsamma. De var mycket långsammare än själva processorn. Så om en enda instruktion kan göra många operationer samtidigt så kommer antalet hämtningar från minnet att bli färre. Fram till 1980-talet satte man likhetstecken mellan en mer effektiv dator och en större instruktionsuppsättning. På den tiden experimenterades det mycket med detta att få mer avancerade instruktioner. Det visade sig dock att assemblerprogrammerare kunde använda dessa instruktioner på ett bra sätt men inte kompilatorerna. Dat fanns olika orsaker till att man på 1980-talet började utveckla RISCprocessorer. En sak var att antalet transistorer på ett mikrochip ökade. Man ville då få hela processorn att rymmas på ett enda mikrochip, och för att lycka med detta så måste man skära ner på hårdvaran. Orsaken varför man ville ha processorn att rymmas på ett anda chip var att det blev billigare. En annan sak var att man började utveckla pipelining tekniker (parellell instruktions exekvering). CISC arkitekturen var inte speciellt lämpad för pipelining eftersom den hade instruktioner av varierande längd och med varierande exekveringstider. De första RISC-processorerna var byggda på ett mycket begränsat utrymme och hade därför en väldigt liten instruktionsuppsättning. Dessa processorer hade inget stöd i hårdvaran för flyttalsberäkningar och vissa hade inte ens integer multiplikation. Dessa sköttes med rutiner i mjukvaran som använde sig av flera enklare instruktioner, en sorts mikrokod (microcode). Dessa tidiga RISC-processorer blev ingen större framgång främst p.g.a. att de var nya och de använde för mycket minnesreferenser, 5

vilket ledde till att minnet blev en flaskhals. Detta problem löstes senare med cacheminnen. Det finns ett antal saker som anses vara karakteristiska för RISC-arkitekturer. Dessa är: Pipelining Flyttalsberäkning i pipeline Alla instruktioner lika långa Delayed branching (fördröjt hopp, p.g.a. datakonflikter) Load/Store arkitekturer (endast speciella instruktioner får accessera minnet direkt) Några enkla och väldefinierade addresseringstyper (addressing modes) Det är dock inte sant att RISC processorer alltid är enklare än CISC, utan snarare tvärtom. Nya RISC processorer har avancerade tekniker så som: funktionell pipeline och sofistikerade minnestekniker och kan även slutföra 2 eller flera instruktioner i samma klockcykel (superscalar) [DowSev1998]. En del av Dessa tekniker behandlas i nästa kapitel. 4. Effektiviseringsmetoder I detta kapitel skall jag berätta om de metoder som finns för att effektivisera instruktions-exekveringen i en modern RISC processor. Främst handlar det om pipelining och metoder för att få själva pipeliningen att fungera som det är tänkt. En annan benämning på pipelining är ILP (instruktion level parallellism), (parallellitet på instruktionsnivå). När pipelinen blir mera komplicerad så kommer den att se väldigt annorlunda ut från den enkla MIPS processor som jag har använt som exempel här. Ett exempel på en sådan pipeline kommer i nästa kapitel som handlar om IA-32 arkitekturen. 6

4.1 Pipelining Pipelining går ut på att instruktionerna överlappar varandra, man kan börja exekvera en ny instruktion även om den första instruktionen inte ännu är slutförd. Detta ger nästan samma prestanda som äkta parallell exekvering men med endast en uppsättning hårdvara [DowSev1998]. Jämfört normal exekvering blir exekvering med pipelining i allmänhet lika många gånger snabbare som det finns steg i pipelinen [HenPat1998]. I pipeline exekvering så är varje instruktion uppdelad i ett antal delar. Dessa kunde vara t.ex. 1. Instruktionshämtning (Instruction fetch IF) Processorn Hämtar en instruktion från minnet 2. Instruktionsavkodning (Instruction decode ID) och Hämtande av operander. Dessa kan vara register eller i minnet. 3. Exekvering (Execution EXE) 4. Minnes access (Memory access MEM) 5. Skrivning till register (Write back WB) Jag skall förklara hur dessa steg fungerar. Det första är instruktionshämtningen. Ett speciellt register Programräknaren (program counter) håller reda på var nästa instruktion finns. En instruktion hämtas från minnet från adressen som specificeras av programräknaren. Programräknaren måste sedan uppdateras. I en arkitektur med 32 bits ord och om inget hopp sker så kommer programräknaren att ökas med 4 för att sedan peka på nästa 32 bits instruktion. Därefter görs avkodning på instruktionen. Det går till så att man plockar ut de enskilda bitarna i instruktionen. Det är färdigt bestämt vilka bitar som specificerar vad. Vissa bitar kan t.ex. bestämma vad för sorts instruktion det är frågan om. Om det är en hoppinstruktion en aritmetisk instruktion en minnesaccessinstruktion etc. Vissa av bitarna kan specificera minnesaddresser andra register. Hårdvaran avkodar dess bitar och styr dem till rätta platser. Bitarna som anger vilken sorts instruktion det är frågan om kopplas till styrenheten. Styrenheten innehåller logik som på basen av vilken sorts instruktion det är frågan om kommer att koppla logiken i 7

processorn på olika sätt. T.ex. om det är frågan om en aritmetisk logisk instruktion med 2 register som operander ser styrenheten till att 2 register kan läsas från registerbanken. I nästa fas hämtas data från minnet eller från register som är specificerade i bitarna som avkodades i föregående fas. När operanderna har hämtats så utförs någon slags exekvering på dessa i den aritmetisk logiska enheten (ALU). Det kan vara t.ex. en aritmetisk operation på 2 integer tal eller att beräkna en effektiv adress med hjälp av innehållet i ett register och en konstant. I nästa steg; minnes access steget görs eventuellt en läsning av eller skrivning till minnet och det är en sådan instruktion. I det sista steget skrivs eventuellt ett resultat tillbaka till ett register. Hela iden med att dela upp en instruktions exekvering i olika faser är att man skall kunna påbörja en ny instruktion varje klockpuls. Så att när den första instruktionen har gått vidare till sitt andra skede (instruktions avkodning) så kan nästa instruktion sättas in, vilket betyder att den instruktionen är i sitt instruktionshämtningsskede. Förloppet har illustrerats i fig1 (från [HenPat2003]). fig1. Bilden visar exekveringen av 5 instruktioner i pipelinen. I den första klockcykeln börjar instruktion i, sitt första skede. I nästa klockcykel kommer instruktion i att ha slutfört sitt första skede (IF-steget) och överfört resultatet till nästa steg (ID-steget), vilket ger möjlighet för instruktion i+1 att påbörja sin exekvering. För att man skall kunna göra allt detta i en pipeline så måste det finnas register som lagrar data mellan en klockpuls till en annan. Dessa register lagrar allt som fanns i den ursprungliga instruktionen, plus hämtad data som behövs senare, uträknade resultat och styrsignaler. Dessa register sätts in mellan de olika stegen: IF, ID, EXE, MEM, WB. fig2 (från [HenPat2003]) illustrerar detta. I bilden är de svarta balkarna pipeline 8

registren. Och mellan dem finns hårdvaran som sköter varje av de 5 stegen i exekveringen [HenPat2003]. fig2. Denna figur visar hårdvaran som behövs för att genomföra enkel pipelining i en MIPS-processor. De olika delarna: IM, REG, ALU etc. separeras av pipeline-register och motsvarar de 5 olika instruktionsstegen i fig 1. I en pipeline så är genomloppet (throughput) det antalet instruktioner som kan slutföras på en tidsenhet. Desto oftare en instruktion blir färdig desto högre blir genomloppet. Tiden det tar att föra en instruktion från ett steg i pipelinen till ett annat är definierat 9

som en processorcykel (processor cycle). Den undre gränsen på en processorcykel bestäms av det längsta steget (det steg som tar längs tid att utföra) i pipelinen. Det finns olika sätt att mäta prestanda i en pipeline. Man kan tänka sig att pipelining sänker antalet klockcykler per instruktion. Ett annat sätt att se på saken är att pipelining minskar tiden för en klockcykel. I en konstruktion utan pipelining kan det hända att det tar 5 eller flera klockcykler att slutföra en instruktion, men med pipelining kan man (i bästa fall) få en instruktion slutförd per klockcykel. En annan möjlighet är att man har en icke pipeline processor som slutför varje instruktion i en mycket lång klockcykel. I det fallet gäller det ju att pipelining förkortar klockcykeltiden. Det finns situationer där nästa instruktion inte kan exekveras i påföljande clockcykel som det är meningen. Dessa situationer kallas konflikter (hazards). Det finns flera olika datakonflikter. Den första är något som kallas en strukturell konflikt (structural hazard). Det innebär att två instruktioner i olika faser av sin exekvering försöker komma åt samma hårdvaruenhet t.ex. minnet. Detta kan lösas t.ex. genom att duplicera minnet eller ha flera cacheminnen. Den andra konflikten är en kontrollkonflikt (control hazard). Det har att göra med att man måste göra ett beslut om hopp innan man har räknat ut de värden som behövs för att avgöra om hoppet skall göras eller inte. Detta löses i praktiken med att estimera hopp (branch prediction) som tas upp i kapitel 4.4. Den tredje och sista typen av konflikt är datakonflikten (data hazard). Detta innebär att data som ännu inte har beräknats behövs i en annan beräkning. Detta kan lösas med hjälp av återkoppling d.v.s. att man sätter in extra ledningar som förbinder de olika enheterna direkt, alltså man kan t.ex. få ett värde direkt från ALU:s utgångar istället för att vänta tills resultatet har skrivits tillbaka till register. För att detta skall funka så behövs en del extra ledningar och logik i kontrollenheten [HenPat1998]. Datakonflikter kan även lösas mera effektivt med dynamisk exekvering, vilket innebär att instruktionernas ordning kastas om för att undvika datakonflikter [HenPat2003]. Dynamisk exekvering tas upp i kapitel 4.3. 10

4.2 Pipelining av funktionella enheter Det är viktigt att man kan utöka pipelinen för att fungera även på enskilda funktionella enheter som t.ex. enheter för flyttalsberäkning och multiplikation, vilka båda är operationer som kan ta ett stort antal klockcykler att utföra. Att utgå från att alla flyttalsoperationer skulle göras i en klockcykel blir väldigt opraktiskt. Det skulle betyda att detta enda steg skulle bli mycket långt och därför kräva en långsam klocka, eftersom hela systemets hastighet är bestämt av det långsammaste steget i pipelinen. Man kan tänka sig att man har en likadan pipeline för flyttal som för vanlig integerberäkning. Man gör 2 förändringar från denna. 1. Exekveringssteget (EXE) kan repeteras så många gånger som det behövs för att slutföra flyttalsberäkningen. 2. Det kan finnas flera flyttalsenheter. När man funderar på dessa problem så är det speciellt 2 saker som man bör ta i betraktande: bundenhet (latency) och repetitionsintervall (repeat interval). Latency definieras som antalet överlappande instruktioner mellan en instruktion som ger ett resultat och en instruktion som använder samma resultat. Repetitionsintervall är antalet cykler som måste passera mellan två instruktioner av samma typ. Typiska exempel på latency och repetitionsintervall ges i fig3 (från [HenPat2003]). fig3. Tabellen visar bundenhet (latency) och repetitionsintervall för olika typer av instruktioner. 11

I det här fallet har integer aritmetiska operationer en latency som är 0, vilket betyder att resultatet kan användas redan i nästa klockcykel. Load instruktioner har en latency som är 1 eftersom resultatet av dem kan användas först efter att en clockcykel har passerat emellan. Det är i den clockcykeln som minnet accesseras med den effektiva adressen som beräknades i Ex-steget, och det är därför logiskt att resultatet av en LOAD finns tillgängligt först efter detta steg Latency för en pipeline definieras som en clockcykel färre än djupet på exekveringsdelen av pipelinen (antalet steg från EXE steget till steget som producerar ett resultat). Fig4 ger ett exempel på en processor med 3 olika flyttals exekveringsenheter och en vanlig integerenhet. Man kan se att det finns ett samband mellan latency för de olika flyttalsoperationerna och djupet på motsvarande enhets pipeline. Djupet på pipelinen är alltid 1 steg större än latency för motsvarande operation. För att få en högre klockfrekvens så måste designern lägga färre logiska operationer i varje steg. Man byter alltså en högre klockfrekvens mot högre latency för operationer. Processorn i fig4 (från [HenPat2003]) kan ha 4 flyttalsadditioner och 7 multiplikationer i samtidig exekvering i pipelinen. Divisionsenheten kan ha endast en division i exekvering åt gången. Det betyder att när en divisions operation har startat så måste man vänta 25 clockcykler, tills hela operationen är färdig innan nästa divisions operation kan matas in i enheten. Detta beror på flyttalsdivisionens höga repetitionsintervall; 25, som syns i fig3. Division är därför en mycket krävande operation som bör undvikas så långt som möjligt. I en konstruktion som i fig4 så kan olika konflikter (hazarder) uppstå. 1. Olika strukturella konflikter kan uppstå. Eftersom operationerna är av varierande längd. 2. När instruktionerna är av varierande längd så kommer de att slutföras i annan ordning än vad de var i den ursprungliga koden [HenPat2003]. 12

fig4. Så har kan det se ut om man utökar MIPS-hårdvaran med flerstegs funktionella enheter för flyttalsmultiplikation addition och division. 4.3 Dynamisk Exekvering Det finns två olika sätt att optimera en dator med pipelining. En av dessa är att göra det statiskt, d.v.s. i mjukvaran. En annan teknik är att göra det dynamiskt, alltså i hårdvaran. Dynamisk exekvering hör till den senare kategorin. Dynamisk exekvering är en viktig teknik som med hjälp av hårdvaran kastar om ordningen på instruktionerna för att undvika datakonflikter. Tekniken har en rad fördelar. Den kan lösa konflikter som var okända vid kompileringen, och underlättar kompilatorns arbete. Dessutom gör den möjligt att kod som var kompilerad för en viss pipeline även kommer att fungera bra på någon annan pipeline. Nackdelen med dynamisk exekvering är att hårdvaran blir mycket mera komplicerad. Tänk dig följande exempel. Man vill addera ihop två operander från minnet och spara tillbaka resultatet till en minnesplats. I vissa CISC arkitekturer skulle detta kunna göras med en enda instruktion. I en typisk RISC arkitektur å andra sidan så krävs 4 instruktioner för att göra detta: 2 load, 1 add och en store. Dessa instruktioner kan inte matas sekventiellt i de festa pipelines utan man blir tvungen att stanna pipelinen vid 13

konflikter. Man kan lösa detta antingen statiskt genom att påverka kompilatorn, eller också kan det göras dynamiskt i hårdvaran. Men om den dynamiska scheduleringen görs bra så får man god prestanda. Därför använder många nya processorer (t.ex. Pentium III och 4) tekniken att ta in komplicerade instruktioner som mikroarkitekturen sedan översätter till dynamiskt schedulerade RISC operationer. Problemet med out-of-order execution (exekvering i oordning) är att den kan leda till olika strukturella konflikter. Jag skall visa en enklare metod kallad scoreboarding (scorekort) som håller reda på de olika instruktionerna för att undvika strukturella konflikter. Iden med en scorekort är att hålla en frekvens om 1 instruktion per klockpuls, genom att starta en operation så tidigt som möjligt. Så att när en instruktion blir stannad (stalled) i pipelinen så kan ändå nästa instruktion starta, förutsatt att den inte är beroende av någon annan instruktion i exekvering. För att hålla reda på vilka instruktioner som kan starta har man ett scorekort. För att man skall ha någon nytta av out-of-order execution så måste man ha flera instruktioner i sitt EXE steg samtidigt, och flera funktionella enheter med hög latency. Varje instruktion går genom scorekortet som konstruerar en tabell över databeroenden. Detta steg kan sägas motsvara ID steget i en vanlig pipeline. Scorekortet avgör sedan när en instruktion kan läsa sina operander och börja exekveringen. Om scorekortet avgör att instruktionen inte kan börja sin exekvering så observerar den alla förändringar i processen och bestämmer när en instruktion kan starta. Scorekortet avgör också när instruktionen kan skriva sitt resultat till destinationsregistret. Fig5 (från [HenPat2003]) visar hur en processor med scorekort kunde se ut. 14

fig5. Bilder visar en implementering av score-kort (score card) för att åstadkomma en enkel form av dynamisk exekvering. De vertikala linjerna är kontrolllinjer. Som utgående från scorekortet kontrollerar hur dataflödet sker över bussarna (de horisontala linjerna). Varje instruktion i scorekortsystemet går genom 4 steg i exekveringen. Stegen är som följande. 1. Issue (utgång). Om en funktionell enhet för instruktionen är ledig och ingen annan aktiv instruktion har samma destinationsregister styr scorekortet instruktionen till rätt funktionella enhet, varefter scorekortet uppdaterar sina interna tabeller. 2. Läsning av operanderna. Skorekortet håller reda på tillgängligheten av källoperanderna. En källoperand är tillgänglig om ingen annan tidigare startad operation kommer att skriva den. När källoperanderna är tillgängliga säger scorekortet till den funktionella enheten att läsa operanderna och starta exekveringen. 15

3. Exekvering. Enheten börjar sin exekvering. När den är färdig anmäler den det till scorekortet. 4. Skriv resultatet. När scorekortet får reda på att operationen är färdig kontrollerar den on det finns någon datakonflikt: den kontrollerar om någon tidigare operation borde läsa registret innan det ändras. Ett exempel på en sådan här konflikt kan illustreras med följande assemblerkod. DIV f0, f2, f4 ADD f10, f0, f8 SUB f8, f8, f14 ADD instruktionen har en källoperand f8 som är samma som SUB-instruktioens destinationsoperand. Men ADD operationen är fördröjd eftersom den är beroende av den långa instruktionen DIV. Här kommer scoreboarden att fördröja SUB instruktionens skriv skede tills ADD instruktionen har hunnit läsa (det gamla värdet på) f8 [HenPat2003]. 4.4 Branch prediction Så kallade hopp (branches) kan även orsaka konflikter i en pipeline. Dessa hopp uppstår alltid när man i källkoden har en loop eller if-sats. Hopp orsakar kontrollkonflikter (control hazards). Antalet hopp som görs när man kör ett program är vanligen ganska många, så det är nödvändigt att ha någon form av branch prediction (uppskattning av hopp). Branch prediction metoder går ut på att i förtid kunna gissa vart nästa hopp skall ske. På så sätt behöver man inte fördröja pipelinen om man har gissat rätt. Jag skriver här om dynamisk branch prediction som är implementerad i hårdvaran. I dynamisk branch prediction är uppskattningen beroende av hur programmet beter sig under exekvering. Det finns även statiska branch prediction metoder som görs av kompilatorn innan programmet startar. Den enklaste formen av branch prediction är en branch prediction-buffer (hopp uppskattnings buffert). Bufferten är en liten bit minne som är lagrar historik över ett visst hopp. I det enklaste fallet har man bara en bit. Biten anger om det har gjorts ett 16

hopp eller inte inom den närmste tiden. Så om biten är satt utgår man från att hoppet kommer att göras och man börjar ladda in nästa instruktion från hoppaddressen. Om uppskattningen visade sig vara fel så inverterar man biten. Denna metod har visat sig vara dålig, så därför använder man istället en 2 bitars buffert. I ett sådant system måste uppskattningen missa 2 gånger förrän den ändras. Denna variant kommer att ge rätt uppskattning oftare än varianten med 1-bits buffert [HenPat2003]. 5. IA-32 arkitekturen IA-32 arkitekturen är Intels processorfamilj, startande från 8086 år 1978. IA-32 är världens populäraste arkitektur för desktop datorer. Senaste modellerna är Pentium 4 och Pentium M, speciellt utformad för bärbara datorer. Nyare Pentium datorer så som Pentium II, III och 4 bygger på avancerade pipelining metoder [HenPat2005]. 5.1 Instruktionsuppsättning och assemblerprogrammering Instruktionerna i IA-32 kan indelas i: Generella instruktioner, flyttalsinstruktioner, MMX-instruktioner, olika sorters SSE-instruktioner, 64-bits instruktioner och speciella systeminstruktioner. De generella instruktionerna är de vanliga instruktioner som kan användas för att skriva enklare program utan desto mera optimering eller prestandakrav. De generella intruktionerna är sådana som finns tillgängliga på alla Intels processorer. Uppsättningen generella instruktioner innehåller: aritmetiska instruktioner (add sub etc.), dataflyttnings instruktioner, logiska instruktioner, dataflöde- och stringoperationer. Instruktionerna kan arbeta på data som finns i de generella registren EAX, EBX, ECX, EDX, EDI, ESI, EBP, och ESP (se fig6 ) och data som finns i minnet. De kan också operera på addresser som finns i minnet eller de generella registren. Även de kortare 16 bits segmentregistren: CS, DS, SS, ES, FS, och GS kan användas för att få fram addresserna [IA32IntMan]. 17

fig6. (från [HenPat2005]) Registren i IA-32 arkitekturen. 80386 processorn var den första i IA-32 familjen som använde 32 bits instruktioner och register. I den gamla 16 bits arkitekturen, som återfanns i 8086, 8088, och 80286 så var de allmänna registren namngivna som: AX, BX, CX, DX. Så när arkitekturen ändrades till 32 bit så behöll man dessa namn, men man satte ett E framför dem för att ange att de var förlängda (extended). Så registren kallas nu EAX, EBX, ECX etc. I 80386 arkitekturen finns 7 allmänna (general purpouse) register. Förutom de allmänna registren finns även 16 bits register som har hållits samma från den tidigare arkitekturen. Dessa är 16 bits registren: CS, SS, DS, ES, FS och GS. Dessa är segmentregister. Till exempel så innehåller CS registret en pekare till platsen i minnet där kodsegmentet börjar [HenPat2005]. 18

De aritmetiska, logiska, data flyttnings (data transfer) operationerna är alla tvåoperands instruktioner. Operand 1 måste vara både destinationsoperand och första källoperand. Detta register alternativt en minnesreferens som är destination kommer alltså att skrivas över. Operand 1 ett kan vara antingen register eller en minnesreferens. Operand 2 kan vara register, konstant eller minnesreferens. Det finns ingen instruktion i vilken båda operanderna är minnesreferenser. Det finns 7 olika addresseringslägen (addressing modes) i IA-32. En minnes operand kan använda vilka addresseringslägen som helst, men det finns en begränsning på vilka register som får användas. T.ex. i register indirekt läget där man har en adress i ett register så får man inte använda ESP eller EBP registret [HenPat2005]. 5.2 Mikroarkitekturen Mikoarkitektur är en metod för att designa komplicerade kontrollenheter. Den använder en enkel hårdvarumotor som kan programmeras att implementera mer komplicerade instruktionsuppsättningar. Mikroprogrammering används idag för att implementera delar av en komplicerad instruktionsuppsättning som t.ex. i en Pentium eller i en dator för specialanvändningsområden [HenPat2005]. P6 är mikroarkitekturen som användes i Pentium Pro Pentium I, Pentium II och Pentium III. Den är föregångare till NetBurst mikroarkitekturen som finns i Pentium 4. P6 är en dynamiskt schedulerad processor. Som översätter varje IA-32 instruktion till en serie mikrooperationer, liknande vanliga RISC operationer. En serie på upp till 3 IA- 32 instruktioner hämtas och översätts till mikrooperationer varje klockcykel. Om en IA- 32 instruktion kräver fler än 4 mikrooperarioner så är det implementerat med hjälp av en mikrokodsekvens som genererar mikrooperationerna i flera klockcykler. Mikrooperationerna är sedan exekverade med hjälp av en dynamisk schedulerad pipeline. 19

5.3 Pipelinen i Pentium 4 Pipelinen i Pentium 4 är en sofistikerad dynamiskt schedulerad pipeline som kan utföra i medeltal 3 mikrooperationer per klockcykel. När det gäller design av sofistikerade processorer så är det svårt att skilja åt de olika delarna från varandra. De funktionella enheterna, cache, register filen, instruktionsutgång (issue) och pipelienekontroll smälter ihop till en enda enhet. Denna brukar allmänt kallas mikroarkitekturen. Fig7 (från [HenPat2005]) visar en modell av mikroarkitekturen hos Pentium 4. Fig7. Schematisk bild över mikroarkitekturen i Pentium4. Pentium 4 har många förbättringar jämfört med sin föregångare III. Dessa är: 1. Pipelinen är dubbelt så djup (20 steg jämfört tidigare 10) 2. Mera funktionella enheter (7 tidigare 5) 20

3. Kan ha ett större antal operationer i samtidig exekvering (126 tidigare 40) 4. Bättre minneshantering I modellen i fig7 kan man se många olika sorters köer. Där finns en Mikrooperationskö (Microoperation que), Integerkö och en flyttals kö. De omfattande köerna tillåter 126 mikrooperationer att vara i flykt samtidigt. I bilden ser det ut som om det skulle finnas endast 6 funktionella enheter och inte 7, men flyttals enheten räknas som två därför att den har en skild enhet för flyttning av flyttal. Load och store enheterna består vardera av två olika delar. Första delen är ansvarig för addressberäkningen och den andra för minnesaccess. Integer ALU enheterna kör på dubbel klockfrekvens jämfört med vad den övriga processorn gör, vilket betyder att vardera integer enhet kan slutföra två integer operationer per vanlig klockcykel. Multimiediaextensioner så som MMX och SSE2 är även inbyggda i flyttalsenheten [HenPat2005]. 5. Avslutning Processorarkitektur är ett avancerat område i pågående utveckling. Det är många nya begrepp att lära sig och även om man tror sig veta grunderna i datorarkitektur kan man lätt känna sig borttappad. Också tillkommer ju det faktum att det finns många olika sorters processorer och de flesta är väldigt olika, med olika instruktionsuppsättningar etc. En sak som jag kom att tänka att tänka på är hur primitiva de gamla processorerna verkar när man jämför med de avancerade konstruktioner som byggs i dag till desktop datorer. Man är nästan förvånad att dessa datorer fungerade överhuvudtaget, men det vet ju alla som har, eller har haft en gammal dator att den ofta fungerar till samma saker bara lite långsammare. I denna uppsats har skummat lätt på ytan av ämnet processordesign utan att gå djupt in de avancerade sakerna som finns i den moderna processorn. Det finns mycket annat som är viktigt när man designar och bygger processorer men som jag inte har tagit upp. Sådana saker är beräkning av en processors prestanda på en teoretisk nivå 21

innan man bygger och mätning och testning av en redan färdig processor. Jag har heller inte tagit upp något speciellt om de minnestekniker som finns. Litteraturlista: [DowSev1998] Kevin Dowd & Charles Severance: High Performance Computing, O Reilly, 1998 [HenPat2003] John L. Hennessy & David A. Pattersson: Computer Architecture, A Qantitative Approach, Morgan Kaufmann, 2003 [HenPat2005] John L. Hennessy & David A. Pattersson: Computer Organization & Design, The Hardware/Software Interface, 3 rd ed, Morgan Kauffmann, 2005 [HenPat1998] John L. Hennessy & David A. Pattersson: Computer Organization & Design, The Hardware/Software Interface, 2 nd ed, Morgan Kauffmann, 1998 [IA32IntMan] IA-32 Intel Architecture Software Developer's Manual <http://www.intel.com/design/pentium4/manuals/index_new.htm> 22