SystemVerilog
SystemVerilog, standardizzato come IEEE 1800, è un linguaggio di descrizione e verifica dell'hardware utilizzato per modellare, progettare, simulare, testare e implementare sistemi elettronici. SystemVerilog è basato su Verilog ed è comunemente usato nell'industria dei semiconduttori e della progettazione elettronica come evoluzione di Verilog. Dal 2008 Verilog e SystemVerilog fanno parte dello stesso standard IEEE. StoriaSystemVerilog nasce nel 2002, con la donazione del linguaggio Superlog ad Accellera da parte della startup Co-Design Automation.[1] La maggior parte delle funzionalità di verifica si basa sul linguaggio OpenVera donato invece da Synopsys. Nel 2005, SystemVerilog è stato adottato come standard IEEE 1800-2005.[2] Nel 2009, lo standard è stato unito allo standard di base Verilog (IEEE 1364-2005), creando lo standard IEEE 1800-2009. La versione attuale è lo standard IEEE 1800-2017.[3] Il set di funzionalità di SystemVerilog può essere suddiviso in due parti distinte:
Il resto di questo articolo discute le caratteristiche di SystemVerilog non presenti in Verilog-2005. Caratteristiche a supporto della progettazioneDurata delle variabiliEsistono due tipi di durata delle variabili specificate in SystemVerilog: static e automatic. Le variabili automatiche vengono create nel momento in cui l'esecuzione del programma rientra nello scope della variabile. Le variabili statiche vengono create all'inizio dell'esecuzione del programma e mantengono lo stesso valore durante l'intero ciclo di vita del programma, a meno che non venga assegnato un nuovo valore durante l'esecuzione. Qualsiasi variabile dichiarata all'interno di un task o di una funzione senza specificare il tipo verrà considerata automatica. Per specificare che una variabile è statica si utilizza la parola chiave Nuovi tipi di datiI tipi di variabili avanzati aggiungono nuove funzionalità al tipo "reg" di Verilog: logic [31:0] my_var;
Verilog-1995 e Verilog-2001 limitano le variabili reg a statement comportamentali come nel caso del codice RTL. SystemVerilog estende il tipo reg in modo che possa essere guidato da un singolo driver come un gate o un modulo. SystemVerilog chiama questo tipo "logic" per ricordare questa capacità ulteriore e che non si tratta di un registro hardware. I nomi "logic" e "reg" sono intercambiabili. Un segnale con più di un driver (come un buffer a tre stati per input/output generico) deve essere dichiarato usando un tipo net come "wire" in modo che SystemVerilog possa risolverne il valore finale. I Packed array multidimensionali unificano ed estendono la nozione di "registri" e "memorie" di Verilog: logic [1:0][2:0] my_pack[32];
Il Verilog classico consente di dichiarare solo una dimensione a sinistra del nome della variabile. SystemVerilog consente qualsiasi numero di tali dimensioni "impacchettate". Una variabile di tipo array packed mappa 1:1 su una quantità aritmetica intera. Nell'esempio precedente, ogni elemento di typedef enum logic [2:0] {
RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW
} color_t;
color_t my_color = GREEN;
initial $display("The color is %s", my_color.name());
Come mostrato sopra, il progettista può specificare un tipo aritmetico sottostante ( Nuovi tipi interi: SystemVerilog definisce Le strutture e le unioni funzionano in modo molto simile al linguaggio di programmazione C. I miglioramenti di SystemVerilog includono l'attributo tagged e l'attributo packed. L'attributo typedef struct packed {
bit [10:0] expo;
bit sign;
bit [51:0] mant;
} FP;
FP zero = 64'b0;
Come mostrato in questo esempio, SystemVerilog supporta anche typedef, come in C e C++. Blocchi proceduraliSystemVerilog introduce tre nuovi blocchi procedurali destinati a modellare l'hardware:
Un blocco always_comb begin
tmp = b * b - 4 * a * c;
no_root = (tmp < 0);
end
Un blocco always_latch
if (en) q <= d;
Un blocco always_ff @(posedge clk)
count <= count + 1;
Gli strumenti EDA (Electronic Design Automation) possono verificare l'intento del progetto controllando che il modello hardware non violi alcuna semantica di utilizzo dei blocchi. Ad esempio, i nuovi blocchi limitano l'assegnazione a una variabile consentendo solo una fonte, mentre Verilog blocca InterfaccePer progetti di piccole dimensioni, le porte Verilog descrivono in modo compatto la connettività di un modulo con l'ambiente circostante. Ma i blocchi principali all'interno di un'ampia gerarchia di progettazione in genere possiedono migliaia di porte. SystemVerilog introduce il concetto di interfacce sia per ridurre la ridondanza delle dichiarazioni dei nomi delle porte tra i moduli collegati, sia per raggruppare e astrarre i segnali correlati in un bundle dichiarato dall'utente. Un concetto aggiuntivo è quello di modport, che mostra la direzione delle connessioni logiche. Ad esempio: interface intf;
logic a;
logic b;
modport in (input a, output b);
modport out (input b, output a);
endinterface
module top;
intf i ();
u_a m1 (.i1(i.in));
u_b m2 (.i2(i.out));
endmodule
module u_a (intf.in i1);
endmodule
module u_b (intf.out i2);
endmodule
Funzionalità di verificaLe seguenti funzionalità di verifica in genere non sono sintetizzabili, il che significa che non possono essere implementate in hardware sulla base del relativo codice HDL. Esse aiutano invece nella creazione di test bench estensibili e flessibili. Nuovi tipi di dati
Il tipo di dati string s1 = "Hello";
string s2 = "world";
string p = ".?!";
string s3 = {s1, ", ", s2, p[2]}; // string concatenation
$display("[%d] %s", s3.len(), s3); // simulation will print: "[13] Hello, world!"
Oltre agli array statici utilizzati nella progettazione, SystemVerilog offre array dinamici, array associativi e code: int cmdline_elements; // # elements for dynamic array
int da[]; // dynamic array
int ai[int]; // associative array, indexed by int
int as[string]; // associative array, indexed by string
int qa[$]; // queue, indexed as an array, or by built-in methods
initial begin
cmdline_elements = 16;
da = new[ cmdline_elements ]; // Allocate array with 16 elements
end
Un array dinamico funziona in modo molto simile a un array unpacked, ma offre il vantaggio di essere allocato dinamicamente in fase di esecuzione (come mostrato sopra). Mentre la dimensione di un packed array deve essere nota in fase di compilazione (da una costante o espressione di costanti), la dimensione dell'array dinamico può essere inizializzata da un'altra variabile, consentendo all'array di essere dimensionato e ridimensionato arbitrariamente secondo necessità. Un array associativo può essere considerato come un albero di ricerca binario con un tipo della chiave e un tipo dei dati specificati dall'utente. La chiave implica un ordinamento. Gli elementi di un array associativo possono essere letti in ordine lessicografico. Infine, una coda fornisce gran parte delle funzionalità del tipo deque della Standard Template Library C++: gli elementi possono essere aggiunti e rimossi da entrambe le estremità in modo efficiente. Queste primitive consentono la creazione di strutture di dati complesse, necessarie ad esempio per lo scoreboard di un progetto di grandi dimensioni. ClassiSystemVerilog fornisce un modello di programmazione orientato agli oggetti. In SystemVerilog, le classi supportano un modello di ereditarietà singola, ma possono implementare funzionalità simili all'ereditarietà multipla attraverso l'uso delle cosiddette "classi di interfaccia" (identiche nel concetto alla funzionalità Le funzionalità di polimorfismo di SystemVerilog sono simili a quelle di C++: il programmatore può definire una funzione L'incapsulamento e l'occultamento dell'informazione (information hiding) vengono eseguiti utilizzando le parole chiave Le istanze delle classi vengono create dinamicamente con laparola chiave Ad esempio: virtual class Memory;
virtual function bit [31:0] read(bit [31:0] addr); endfunction
virtual function void write(bit [31:0] addr, bit [31:0] data); endfunction
endclass
class SRAM #(parameter AWIDTH=10) extends Memory;
bit [31:0] mem [1<<AWIDTH];
virtual function bit [31:0] read(bit [31:0] addr);
return mem[addr];
endfunction
virtual function void write(bit [31:0] addr, bit [31:0] data);
mem[addr] = data;
endfunction
endclass
Constrained random generationAlle quantità intere, definite nella definizione di una classe o come variabili autonome in un certo scope lessicale, possono essere assegnati valori casuali sulla base di un insieme di vincoli. Questa funzionalità è utile per creare scenari randomizzati per la verifica.
Nella definizione di una classe, i modificatori class eth_frame;
rand bit [47:0] dest;
rand bit [47:0] src;
rand bit [15:0] f_type;
rand byte payload[];
bit [31:0] fcs;
rand bit [31:0] fcs_corrupt;
constraint basic {
payload.size inside {[46:1500]};
}
constraint good_fr {
fcs_corrupt == 0;
}
endclass
Nell'esempio precedente, il campo Metodi di randomizzazioneIn ogni classe SystemVerilog ci sono 3 metodi predefiniti per la randomizzazione: pre_randomize, randomize e post_randomize. Il metodo randomize viene chiamato dall'utente per la randomizzazione delle variabili di classe. Il metodo pre_randomize viene chiamato dal metodo randomize prima della randomizzazione e il metodo post_randomize viene chiamato dal metodo randomize dopo la randomizzazione. class eth_frame;
rand bit [47:0] dest;
rand bit [47:0] src;
rand bit [15:0] f_type;
rand byte payload[];
bit [31:0] fcs;
rand bit corrupted_frame;
constraint basic {
payload.size inside {[46:1500]};
}
function void post_randomize()
this.calculate_fcs(); // update the fcs field according to the randomized frame
if (corrupted_frame) // if this frame should be corrupted
this.corrupt_fcs(); // corrupt the fcs
endfunction
endclass
I metodi constraint_mode() e random_mode() sono usati per controllare la randomizzazione. constraint_mode() viene utilizzato per attivare e disattivare un vincolo specifico e random_mode viene utilizzato per attivare o disattivare una randomizzazione di una variabile specifica. Il codice seguente descrive e verifica proceduralmente un frame Ethernet: class eth_frame;
rand bit [47:0] dest;
rand bit [47:0] src;
rand bit [15:0] f_type;
rand byte payload[];
bit [31:0] fcs;
rand bit corrupted_frame;
constraint basic {
payload.size inside {[46:1500]};
}
constraint one_src_cst {
src == 48'h1f00
}
constraint dist_to_fcs {
fcs dist {0:/30,[1:2500]:/50}; // 30, and 50 are the weights (30/80 or 50/80, in this example)
}
endclass
.
.
.
eth_frame my_frame;
my_frame.one_src_cst.constraint_mode(0); // the constraint one_src_cst will not be taken into account
my_frame.f_type.random_mode(0); // the f_type variable will not be randomized for this frame instance.
my_frame.randomize();
AsserzioniLe asserzioni sono utili per verificare le proprietà di un progetto che si manifestano dopo che è stata raggiunta una condizione o uno stato specifico. SystemVerilog ha un proprio linguaggio di specifica delle asserzioni, simile al Property Specification Language. Il sottoinsieme dei costrutti del linguaggio SystemVerilog che supporta le asserzioni è comunemente chiamato SystemVerilog Assertion o SVA.[4] Le asserzioni SystemVerilog sono costruite da sequenze e proprietà. Le proprietà sono un superinsieme di sequenze; qualsiasi sequenza può essere utilizzata come se fosse una proprietà, sebbene ciò non sia tipicamente utile.
Le sequenze sono costituite da espressioni booleane aumentate con operatori temporali. L'operatore temporale più semplice è l'operatore sequence S1;
@(posedge clk) req ##1 gnt;
endsequence
Si avrà una corrispondenza se il segnale Altri operatori sequenziali includono operatori di ripetizione e varie congiunzioni. Questi operatori consentono al progettista di esprimere relazioni complesse tra i componenti del progetto.
Un'asserzione tenta continuamente di valutare una sequenza o una proprietà. L'asserzione fallisce se la proprietà fallisce. La sequenza sopra fallirà ogni volta che property req_gnt;
@(posedge clk) req |=> gnt;
endproperty
assert_req_gnt: assert property (req_gnt) else $error("req not followed by gnt.");
Questo esempio mostra un operatore di implicazione Oltre alle asserzioni, SystemVerilog supporta le ipotesi e la copertura delle proprietà. Un'assunzione stabilisce una condizione che uno strumento formale di dimostrazione logica deve assumere come vera. Un'asserzione specifica una proprietà che deve essere dimostrata vera. Nella simulazione, sia le asserzioni che le ipotesi vengono verificate rispetto agli stimoli del test. La copertura della proprietà consente all'ingegnere di verifica di verificare che le asserzioni stiano monitorando accuratamente il progetto. CoperturaLa copertura (coverage) applicata ai linguaggi di verifica hardware si riferisce alla raccolta di statistiche basate su eventi di campionamento all'interno della simulazione. La copertura viene utilizzata per determinare quando il dispositivo sottoposto a test (Device Under Test, DUT) è stato esposto a una varietà sufficiente di stimoli tale che vi sia un'elevata probabilità che il DUT funzioni correttamente. Si noti che questa definizione differisce dal concetto di copertura del codice (software), orientata a garantire che tutte le righe del codice nel progetto siano state eseguite. La copertura funzionale assicura che tutti i casi corner e marginali desiderati all'interno dello spazio di progettazione siano stati esplorati. Un gruppo di copertura SystemVerilog crea un database di "contenitori" (bin) che memorizzano un istogramma di valori di una variabile associata. È inoltre possibile definire la copertura incrociata, che crea un istogramma che rappresenta il prodotto cartesiano di più variabili. Un evento di campionamento controlla quando viene prelevato un campione. L'evento di campionamento può essere un evento Verilog, l'entrata o l'uscita di un blocco di codice o una chiamata al metodo Per esempio: class eth_frame;
// Definitions as above
covergroup cov;
coverpoint dest {
bins bcast[1] = {48'hFFFFFFFFFFFF};
bins ucast[1] = default;
}
coverpoint f_type {
bins length[16] = { [0:1535] };
bins typed[16] = { [1536:32767] };
bins other[1] = default;
}
psize: coverpoint payload.size {
bins size[] = { 46, [47:63], 64, [65:511], [512:1023], [1024:1499], 1500 };
}
sz_x_t: cross f_type, psize;
endgroup
endclass
In questo esempio, l'ingegnere di verifica è interessato alla distribuzione dei frame broadcast e unicast, al campo size/f_type e alla dimensione del payload. Gli intervalli nel punto di copertura delle dimensioni del payload riflettono i corner case di interesse, inclusi i frame di dimensioni minime e massime. SincronizzazioneUn ambiente di test complesso è costituito da componenti di verifica riutilizzabili che devono comunicare tra loro. La primitiva "event" di Verilog consente a diversi blocchi di istruzioni procedurali di attivarsi a vicenda, ma l'applicazione della sincronizzazione dei thread dipende dall'uso (intelligente) da parte del programmatore. SystemVerilog offre due primitive specifiche per la sincronizzazione tra thread: mailbox e semaphore. La mailbox è modellata come una coda di messaggi FIFO. Opzionalmente, una FIFO può essere parametrizzato dal tipo in modo che solo gli oggetti del tipo specificato possano essere passati attraverso di esso. Tipicamente, gli oggetti sono istanze di classi che rappresentano transazioni : operazioni elementari (ad esempio, l'invio di un frame) che vengono eseguite dai componenti di verifica. Il semaforo è modellato come un semaforo di conteggio. Miglioramenti generali al Verilog classicoOltre alle nuove funzionalità di cui sopra, SystemVerilog migliora l'usabilità delle funzionalità linguistiche esistenti di Verilog. Di seguito sono riportati alcuni di questi miglioramenti:
Oltre a questo, SystemVerilog include un'interfaccia con altri linguaggi (come C/C++) detta SystemVerilog DPI (Direct Programming Interface). Software di verifica e sintesiNella progettazione di chip elettronici, SystemVerilog è ampiamente utilizzato nella verifica. I tre maggiori fornitori di strumenti EDA (Cadence Design Systems, Mentor Graphics, Synopsys) hanno incorporato SystemVerilog nei loro simulatori HDL in linguaggio misto. Sebbene nessun simulatore possa ancora rivendicare il supporto completo del SystemVerilog Language Reference Manual, rendendo l'interoperabilità dei test bench una sfida, sono in corso sforzi per promuovere la compatibilità tra fornitori. Nel 2008, Cadence e Mentor hanno rilasciato la Open Verification Methodology, una libreria di classi open source e un framework di utilizzo per facilitare lo sviluppo di test bench e IP di verifica riutilizzabili. Synopsys, che era stata la prima a pubblicare una libreria di classi SystemVerilog (VMM), ha successivamente risposto rendendo disponibile e open la propria VMM. Molti provider di terze parti hanno annunciato o già rilasciato IP di verifica SystemVerilog. Nella sintesi del progetto (trasformazione di una descrizione del progetto hardware in una netlist), l'adozione di SystemVerilog è stata lenta. Molti team di progettazione utilizzano flussi di progettazione che coinvolgono più strumenti di fornitori diversi. La maggior parte dei team di progettazione non può migrare a progetti RTL basati su SystemVerilog fino a quando l'intera suite di strumenti front-end (linter, verifica formale e generatori di strutture di test automatizzate ) non supporta un sottoinsieme linguistico comune[senza fonte]. Note
Bibliografia
Voci correlateCollegamenti esterni
Lo standard SystemVerilog più recente è accessibile gratuitamente tramite IEEExplore.
|