Ved du med sikkerhed, at din RISC-V RTL ikke indeholder nogen overraskelser?

Kildeknude: 1600300

I betragtning af den relative nyhed og kompleksitet af RISC-V RTL-designs, uanset om du køber en kommercielt understøttet kerne eller downloader et populært open source-tilbud, er der den lille, men ikke-nul risiko for, at uønskede overraskelser slipper uopdaget ind i dit slutprodukt. I rækkefølge af høj til lav sandsynlighed skal du overveje:

  • Tilstedeværelsen af ​​en underlig-men-fuldstændig-mulig hjørne-case-fejl
  • Fejl "inde i" de brugerdefinerede instruktioner, som du eller din leverandør opretter til din applikation
  • Fejl "ved kanterne" af en brugerdefineret instruktion - f.eks. udføres instruktionen korrekt, men den efterlader på en eller anden måde maskinen i en beskadiget tilstand
  • Relateret: udokumenterede og/eller dårligt specificerede nye funktioner, der uforvarende åbner huller i designet
  • Ondsindet trojansk logik indsat i det skjulte via et forsyningskædeangreb

Fælles afbødende tilgange

Naturligvis er den første forsvarslinje ekspertinspektion af den indkommende eller udviklende RTL-kode. Dette bør naturligvis gøres; men det burde være lige så indlysende, at denne teknik - som man siger i den matematiske verden - "er nødvendig, men ikke tilstrækkelig" (selvom du fik professor Patterson til selv at gennemgå din kode).

Den næste forsvarslinje er at anvende simulationsbaserede tilgange: Instruction Set Simulation (ISS), automatiseret sammenligning af din DUT med modne gyldne modeller, begrænset tilfældige UVM-testbænke til DUT RTL-simulering og endda at overføre virkelige stimulus til hardware-assisteret emulering af DUT. Igen, disse tilgange er alle værdifulde og bør gøres; men de lider alle af den samme fejl: de er i sagens natur ufuldstændige, da de er afhængige af stimulusgenerering. For eksempel, i det ekstreme, men mulige tilfælde af et forsyningskædeangreb, har den trojanske logikudvikler bevidst skabt en udløsende sekvens af signalering og data, der sandsynligvis vil undslippe opdagelse af selv den mest kreative white hat hacker. Og selvfølgelig har funktionelle fejl deres egen måde at bruge naturligt forekommende entropi til at forblive skjult.

Den nederste linje er, at den eneste måde at være helt sikker på, at din RISC-V RTL er fri for naturlige eller ondsindede overraskelser, er at anvende udtømmende, formelle metoder til at verificere designet.

Lettere sagt end gjort, ikke?

Ja og nej: For 14 år siden kunne denne form for analyse kun udføres af forskere på ph.d.-niveau, der brugte deres egne håndlavede programmer. Men siden 2008 er værktøjerne og teknikkerne blevet fremstillet således, at alle, der er fortrolige med det grundlæggende i formel verifikation og skrivningen af ​​IEEE-standarden System Verilog Assertions (SVA) hurtigt kan anvende og få succes her.

En formel-baseret proces i tre trin

Det anbefalede formel-baserede flow udfolder sig som følger:

  1. Opret en formel testbench, der "modellerer" DUT-specifikationen
  2. Definer de inputbegrænsninger og kontroller, der skal køres mod DUT
  3. Udfør analyse

Trin 1 – Opret en formel testbench, der "modellerer" DUT-specifikationen

Grundlaget for denne metode er at skrive et sæt egenskaber, der repræsenterer adfærden af ​​hver instruktion i dit RISC-V-design. Opgaven er at fange effekten af ​​en given instruktion på IP'ens output og interne arkitektoniske tilstande (i RISC-V-verdenen er dette programtælleren (PC) og registerfilen (RF)) for enhver given vilkårlig lang inputsekvens. Dette gøres ved hjælp af en specialbygget udvidelse til IEEE SVA kaldet Operational SVA. I en nøddeskal er dette et bibliotek, der leveres med det formelt baserede processorverifikationsværktøj; og fra verifikationsingeniørens synspunkt ligner det en intuitiv delmængde af velkendt SVA-kode. Figur 1 viser den generiske struktur:

ejendomsinstruktion_A; // konceptuel tilstand t ##0 ready_to_issue() og // trigger t ##0 opcode==instr_A_opc antyder // konceptuel tilstand t ##0 ready_to_issue() og // hukommelsesgrænseflader output // læs næste instruktion t ##0 imem_access(instr_A_opc) og // dataindlæsning/lager t ##1 dmem_access(instr_A_opc) og // arkitektoniske registre t ##1 RF_update(instr_A_opc) og t ##1 PC_update(instr_A_opc) endproperty 

Fig. 1: Struktur af operationel SVA-kode, der fanger specifikationen af ​​en processorinstruktion. [1]

Med henvisning til figur 1, venstre side af implikation (delen af ​​koden over nøgleordet indebærer) identificerer, hvornår maskinen er klar til at udstede en ny instruktion, og den instruktion, der udstedes. Påstanden fanger de aktuelle værdier af de arkitektoniske tilstande og i højre side af implikationen (del af kode jf. nedenstående nøgleordet indebærer), beviser deres næste værdier.

Derudover skal processorens output bevises korrekt - i dette tilfælde for at sikre, at instruktionen får adgang til de forventede data og instruktionshukommelsesplaceringer. Påstanden beviser også, at maskinen er klar til at udstede en ny instruktion på næste cyklus. Dette er afgørende for at afkoble verifikationen af ​​en instruktion fra sekvensen af ​​instruktioner, som den kunne være en del af. For eksempel kunne instruktion A udføres korrekt, men efterlade maskinen i en beskadiget tilstand. Denne fejlagtige tilstand kan få den næste instruktion B til at producere forkerte resultater uden egen skyld. Med den operationelle SVA-tilgang ville den påstandsbekræftende instruktion B bestå, mens den påstandsbekræftende instruktion A ville mislykkes (hvor læse- og skrivehukommelsesoperationer kunne vare adskillige cyklusser).

Bundlinje: funktionerne, der repræsenterer arkitektoniske tilstande i Operational SVA-koden, skal afbildes til implementeringssignalerne og skal afspejle processorens mikroarkitektur. Status for RF kan for eksempel afhænge af aktiveringen af ​​videresendelsesstier. [1]

[Bemærk: For dem af jer, der er bekendt med enten simulering eller formel funktionel dækning, er denne forestilling om fuldstændighed ikke afhængig af strukturelle dækningsmålinger eller på at skabe og indsamle målinger til en funktionel dækningsmodel. I stedet for (og at komme lidt foran de resterende trin og resultater) handler analyseoutputtet her om at få fuldstændige beviser for alle egenskaberne. Fuldstændige beviser viser også implicit, at der ikke er nogen anden funktionalitet - som var uspecificeret eller uventet (specifikation eller kodningsfejl) eller ondsindet indsat - som ikke er fanget af dette sæt egenskaber. Omformuleret handler denne metode om at opnå 100 % "testplandækning" som bekræftet af de udtømmende formelle analyseresultater - hvor intet er mere "fuldstændigt" end et matematisk bevis!]

Trin 2 – Definer de inputbegrænsninger og kontroller, der skal køres mod DUT

For at supplere specifikationsegenskaberne for hver instruktion er næste trin at definere inputbegrænsningerne og eventuelle yderligere outputchecks. Igen anvendes Operational SVA, hvor brugeren nu specificerer en "fuldstændighedsplan" for at definere både lovlige input og ulovlige signaler, som DUT'en skal ignorere. I henhold til eksemplet vist i figur 2 er der tre sektioner: bestemmelsesantagelser, bestemmelseskrav og egenskabsgraf.

fuldstændighed processor; bestemmelse_antagelser: // INPUTS bestemt(imem_data_i); bestemt(dmem_valid_i); if (dmem_valid_i) bestemt(dmem_data_i) endif; determination_requirements: // OUTPUTS bestemt(imem_read_o), if (imem_read_o)bestemt(imem_addr_o) endif; bestemt(dmem_enable_o); if (dmem_enable_o) determined(dmem_rd_wr_o), determined(dmem_addr_o) endif; // Arkitektoniske stater bestemt(PC); bestemt(RF); property_graph: alle_instruktioner := instruktion_ikke_a, instruktion_tilføj_a, instruktion_under_a, [...] alle_instruktioner -> alle_instruktioner; ende fuldstændighed; 

Fig. 2: Eksempel på en fuldstændighedsplan med betingede fastsættelsesforudsætninger og krav.

For at uddybe:

  • "determination_assumptions" er simpelthen et fancy navn for inputværdibegrænsninger
  • "determination_requirements" er en definition af de signaler, der skal verificeres (både processorens udgangssignaler og arkitektoniske tilstande)
  • Sektionen "egenskabsgraf" er simpelthen en binding af denne fil til alle de egenskaber, der blev oprettet i trin 1

Opsummering af, hvor vi er på dette tidspunkt: I trin 1 skabte du, hvad der faktisk er en cyklus-nøjagtig model af DUT, som skal bevises sand for alle tider og alle input; i trin 2 opsætter du de begrænsninger og enhver speciel adfærd, du skal være opmærksom på. Tilføj disse sammen, og i virkeligheden har du en formel testbench, der er klar til at køre!

Trin 3 – Udfør analyse

Målet med alle formelle værktøjer er udtømmende at bevise, at alle egenskaber er sande til enhver tid og alle input. I tilfælde af RISC-V-processorverifikation arbejder værktøjet på at bevise, at enhver vilkårlig lang inputsekvens kan matches til en unik sekvens af den specificerede Operationelle SVA, der forudsiger værdierne af output og arkitektoniske tilstande.

Og det er præcis, hvad der sker. Hvis der er nogen forskel i adfærd detekteret mellem specifikationen og DUT, leverer det formelle værktøj en "modeksempel"-bølgeform, der viser nøjagtig den række af inputsignaler og data, der kan skabe en overtrædelse af specifikationen. Som nævnt ovenfor kan sådanne fejl findes i det indre af instruktionens RTL-logik eller i "overdragelseslogikken", der starter den næste lovlige gren/instruktion.

Uanset hvad, når disse problemer er rettet, og værktøjet beviser alle egenskaberne, er resultaterne virkelig "komplette" - dvs. du kan være matematisk sikker på, at der ikke er nogen RTL-kodningsfejl - den formelle analyse har bogstaveligt talt bevist fraværet af nogen fejl !

Resultater

For det første, som nævnt ovenfor, har mange processorudviklere i årenes løb nydt godt af dette flow [2], [3], [4].

Ved at afprøve denne metode med RISC-V lavede mine kolleger et casestudie ved at bruge den populære Rocket Chip open source-kerne. Specifikt blev RV64IMAFDC – sv39 vm-konfigurationen undersøgt. Dette er en 64-bit processorkerne med et 39-bit virtuelt hukommelsessystem [5] og udvidelser, såsom komprimerede og atomiske instruktioner [6]. Denne open source, RISC-V ISA-implementering bruger en fem-trins, enkelt-udgave, i rækkefølge pipeline med out-of-order afslutning til instruktioner med lang ventetid, såsom division eller cache-misser. Kernen understøtter også grenforudsigelse og runtime-modifikation af "misa"-registret, hvilket gør det muligt at slukke for visse instruktionssæt-udvidelser.

Selvom dette øjebliksbillede af Rocket Chip var blevet grundigt verificeret og tapet flere gange, blev fire tidligere ukendte, mistænkelige adfærdsmønstre identificeret og rapporteret til Rocket Core RTL-udviklerne. Disse problemer ([7], [8], [9] og [10]) blev opdaget udelukkende gennem den systematiske anvendelse af den komplette formelle verifikationstilgang, der er beskrevet i denne artikel.

Uddybende [10] specifikt - opdagelsen af ​​en ikke-standard instruktion CEASE (Opcode 0x30500073) i RTL: Det er klart, at Rocket Chip-teamet faldt bagud med deres dokumentation (og de rettede dette næsten øjeblikkeligt efter indgivelsen af ​​GitHub pull-anmodningen). Den større pointe er, at dette viser, at den logik, der kræves for at implementere en hel instruktion - snesevis af kodelinjer og mange porte af syntetiseret, placeret og dirigeret logik - kan undslippe detektion ved visuel inspektion, RTL-simulering, gateniveausimulering, hele back-end implementeringsproces og hardwareprototyper i laboratoriet!

Men hvad med ydelsen af ​​dette flow?

Lad os først tage fat på den større betydning af "ydeevne". På grund af den nye karakter af Rocket Chip-designet tog det omkring 20 ingeniør-uger for vores formelle verifikationsudøvere at udvikle hele testbænken og begrænsninger. Tidligere anvendelser af dette flow på mere struktureret, kommerciel IP har dog typisk taget en brøkdel af denne tid. Naturligvis vil hele opdragsprocessen gå meget hurtigere, jo mere stabile og modne specifikationerne er, hvor veldokumenteret og læsbar DUT RTL-koden er, og hvor meget adgang du har til designingeniørerne til spørgsmål og svar.

Da først miljøet var konfigureret, var vægurets køretid hele 2 timer - dvs. meget mindre, end du med rimelighed kunne forvente fra begrænset tilfældig RTL-simulering og endda hardware-assisteret verifikation. Husk desuden, at resultaterne af denne analyse er gyldige for alle input og hele tiden - med et ord, de er udtømmende [11].

Resumé

Den komplette, formelt baserede processorverifikationstilgang, der præsenteres i denne artikel, bruger en udvidelse til IEEE SVA, Operational SVA, til formelt at verificere, at en RISC-V ISA er fri for huller og uoverensstemmelser. I modsætning til tilfældige simuleringstestbænke, emulering eller fysisk prototyping, registrerer det komplette sæt af egenskaber og begrænsninger udtømmende mange typer af RTL-fejl, såvel som tilstedeværelsen af ​​udokumenteret eller dårligt specificeret kode og ondsindede trojanske heste.

Referencer

1 – 2019 GOMACTech Conference, Albuquerque, NM, 28. marts 2019: Fuldstændig formel verifikation af RISC-V-processor IP'er for trojanske frie betroede IC'er, David Landoll, et.al.

2 – DVCon 2007: Komplet formel verifikation af TriCore2 og andre processorer, Infineon Gmbh.

3 - 51st Design Automation Conference (DAC): Formel verifikation anvendt på Renesas MCU Design Platform ved hjælp af OneSpin-værktøjerne

4 – DVCon Europe 2019: Komplet formel verifikation af en familie af automotive DSP'er, Bosch Gmbh.

5 – RISC-V-instruktionssætmanualen, bind II: Privileged Architecture, dokumentversion 1.10.

6 - https://github.com/freechipsproject/rocket-chip [tilganget 20. december 2018]

7 – DIV-instruktionsresultat er ikke skrevet til registerfil
https://github.com/freechipsproject/rocket-chip/issues/1752

8 – JAL- og JALR-instruktioner Opbevar anden retur-pc
https://github.com/freechipsproject/rocket-chip/issues/1757

9 – Ulovlige opkoder afspilles igen og forårsager uventede bivirkninger
https://github.com/freechipsproject/rocket-chip/issues/1861

10 – Ikke-standard instruktion CEASE (Opcode 0x30500073) Opdaget i RTL, https://github.com/freechipsproject/rocket-chip/issues/1868

11 - Verification Horizons blog, hvordan kan du sige, at formel verifikation er udtømmende?, Joe Hupcey III
https://blogs.sw.siemens.com/verificationhorizons/2021/09/16/how-can-you-say-that-formal-verification-is-exhaustive/

Kilde: https://semiengineering.com/do-you-know-for-sure-your-risc-v-rtl-doesnt-contain-any-surprises/

Tidsstempel:

Mere fra Semiconductor Engineering