Chapter 1: SystemC, Joined design at system level (based on SystemC 2.2) B. Miramond M2 – S2IC/ESA B. Miramond - UCP Plan du chapitre I. II. III. IV. Introduction Programmer en SystemC Noyau de simulation Niveaux d’abstraction : une méthodologie de conception VI. Modélisation matérielle en SystemC VII. Modélisation TLM VIII. Concepts avancés B. Miramond - UCP (30min) (1h30) (1h) (30min) (30min) (1h) (30min) I. SystemC … What else ? B. Miramond - UCP Plan de la section I 1. 2. 3. 4. 5. 6. Motivations Historique Qu’est ce que SystemC Les concurrents Les librairies SystemC Quelques définitions pour démarrer B. Miramond - UCP 1) Motivations Changement d’échelle : conception de «systèmes» sur puce. Sur des technos plus anciennes, la conception reliait un microprocesseur, une mémoire et un ASIC (accélérateurs matériels). Des experts réalisaient alors le partitionnement de l’application entre les parties logicielles et matérielles. Pour la partie Hw, la spécification des ASICs correspondait à qqs milliers de portes. Ce qui restait exprimable dans un langage HDL à un niveau RTL. RTL : Register Transfer Level B. Miramond - UCP Register Tranfer Level A legacy from HDL RTL description is a way of describing the operation of a synchronous digital circuit. In RTL design, a circuit's behavior is defined in terms of the flow of signals (or transfer of data) between hardware registers, and the logical operations performed on those signals. Vhdl process(clk) begin if rising_edge(clk) then Q <= not Q; end if; end process; The term refers to the fact that RTL focuses on describing the flow of signals between registers B. Miramond - UCP Et maintenant … Aujourd’hui, la technologie des SoCs autorise la présence de plusieurs proc., microcontrôleurs 32 bits ou DSP. On-chip memory Accélérateurs matériels pour fonctions dédiées Contrôleurs de périphériques Le tout relié par un réseau complexe de communication. A ce niveau de complexité, le partitionnement n’est plus évident entre logiciel et matériel. La conception matérielle s’exprime en millions de portes. B. Miramond - UCP SoC Architecture Debug port JTAG ARM 946E core Arbiter Bridge Timer ICache Boot ROM DCache SDRAM/Flash Multiport memory HW coprocessor RISC core DMA Controler UART RAM Arbiter B. Miramond - UCP DSP ADC/DAC Conception cost evolution System Level Methodology Intelligent Testbecnh Large block Reuse $ 10.000.000.000 Small thin Eng. In House P&R $ 100.000.000.000 Small block Reuse Conception cost IC Implementatrion [Roadmap for Semiconductors 2001] predicted measured $ 1.000.000.000 $ 100.000.000 $ 10.000.000 1985 1990 1995 2000 B. Miramond - UCP 2005 2010 2015 2020 Conception niveau système La prise de décision de l’implantation est repoussée car elle doit être explorée. Donc, pour décrire des systèmes encore à la fois logiciels et matériels il faut aller au-delà du niveau RTL, et à ce niveau les HDLs ne sont plus adaptés. On parle de conception au niveau système. Et du besoin de langage de modélisation supportant ce niveau. B. Miramond - UCP 2) Positionnement du langage Requirements Matlab, SPW, S. Studio Specifications HW/SW Behavior SystemC Functional Verification Test bench RTL Verilog VHDL System Verilog Gates Transistor B. Miramond - UCP Objectifs Environnement unifié de description matériel et logiciel Explorer les solutions de conception en travaillant à un niveau système => Améliorer la productivité des concepteurs de systèmes électroniques. B. Miramond - UCP 3) Donc qu’est ce que SystemC ? SystemC est un langage de modélisation au niveau système Réseau de processus communiquant (HDL) Supportant différents modèles de traitements (MoCs) Permettant de modéliser des systèmes logiciels et matériels C’est aussi un environnement de simulation temporelle (eventdriven simulation, cf. HDL). Basé sur une librairie de classes C++ Open Source SystemC n’est pas une méthodologie, mais vous avez besoin d’une méthodologie pour l’utiliser ! B. Miramond - UCP Méthodologie de conception Spécifications Software (C/C++) Cosimulation Modèle TLM Environnement de test (SystemC) Modèle RTL (HDL/SystemC) Synthèse Portes Layout Software Hardware B. Miramond - UCP Testbench Quelques définitions Niveau d’abstraction = est un niveau de description d’un système apportant un niveau de détails données. Un flot de conception est une succession de niveaux d’abstraction. Raffinement = Le raffinement est le mécanisme permettant de passer d’un niveau d’abstraction à un autre. Celui-ci doit être le plus possible automatisable. Spécification exécutable = est un modèle fonctionnel qui fournit le comportement d’un composant quelque soit le niveau d’abstraction et de manière indépendante de l’implémentation (plateforme). B. Miramond - UCP Caractéristiques du langage SystemC 1. 2. 3. 4. 5. 6. Spécification et conception à différents niveaux d’abstraction Intégration de portions de logiciel embarqué, à la fois sous la forme de modèles et de code : réutilisation, Création de spécification exécutables. Création de plateformes exécutables sur lesquelles seront mappées les spécifications. Simulations rapides pour permettre l’exploration de l’espace de conception (spécifications + plateformes) Structuration des modèles autorisant la séparation de la fonctionnalité et de la communication Adaptation flexible (IPs) Besoin de réutilisation B. Miramond - UCP Propriétés supplémentaires Basé sur un langage de programmation existant pour bénéficier des outils de compilation, de debug, … Un langage orienté objet fournirait les mécanismes de base pour la flexibilité des modèles et la réutilisation. (héritage, templates…) B. Miramond - UCP 4) Historique Synopsys- SCENIC LWG / OSCI Adelante AJRT Lib Fixed Point Types IMEC CoWare N2C SystemC 1.0 Master-Slave Lib SystemC 1.2.1 Beta Channels SystemC 2.0 Bug fix SystemC 2.0.1 Dynamic Processes SystemC 2.1 puis 2.2 RTOS / Software SystemC 3.0 B. Miramond - UCP Future 4) Les concurrents Sur le créneau de la modélisation niveau système : SpecC – D. Gajski de l’Université de Irvine OCAPI - IMEC http://www.imec.be/design/ocapi/unified_design.shtml Cynlib – CynApps http://www.ics.uci.edu/~specc/ http://www.forteds.com/technology/esl2gdsii.asp … B. Miramond - UCP 5) Librairies SystemC (sup.) The SystemC Verification Library (SCV) Architecture Description Language : ArchC Extension de SystemC pour la description de processeurs http://www.archc.org Master/Slave library Ajoute de fonctionnalités pour la vérification des design (Cadence) Langage de développement de testbench (Testbuilder) Constrained randomization, introspection, transaction recording http://www.testbuilder.net Protocole de communication http://www.systemc.org The Boost Library (C++) Free peer-reviewed portable C++ source libraries http://www.boost.org B. Miramond - UCP Bibliographie Books System Design with SystemC (4th edition), Grötker et al., Kluwer Academic Publisher, 2004 From the ground-up (SystemC 2.1), D. Black & J. Donovan, Kluwer Academic Publisher, 2005 Bib. Ensea, dispo Transaction level modeling with SystemC : TLM concepts and applications for embedded systems, by Frank Ghenassia, Springer 2005. Ensea, emprunté Bib. Ensea, dispo SystemC kernel extensions for heterogeneous system modeling : a framework for Multi-MoC modeling & simulation, by Hiren D. Patel and Sandeep K. Shukla, 2004 Ensea, dispo Weblinks http://www.systemc.org B. Miramond - UCP I. Programmer en SystemC B. Miramond - UCP Plan de partie II Architecture du langage Les structures 1. 2. 1. 1. 2. 3. 4. Port Channels Interfaces Hierarchical Channels Processus Évènements 4. 5. 1. 2. sc_events notification Sensibilité 1. 2. sc_module Ports, Channels et Interfaces 3. 1. 3. 4. 2. 3. 4. Statique Dynamique Composition d’évènements Timeout Exemple de synthèse Quelques exemples supplémentaires Debugging 1. 2. 3. 4. B. Miramond - UCP Debug Environnement Testbench results Waveform tracing Resulting waveforms 1. Architecture du langage http://www.systemc.org Librairies SystemC téléchargeables gratuitement European SystemC Users Group http://www-ti.informatik.uni-tuebingen.de/~systemc B. Miramond - UCP Methodology Specific Libraries Standard Channels Kahn Process Network, Static Dataflow, Etc. Master/Slave Library, etc. Elementary Channels Signal, Timer, Mutex, FIFO… Core Language Data-Types Modules Ports Processes Events Interfaces Channels 4-valued logic types (O1XZ) 4valued logic vectors Bits and bit-vectors Arbitrary-precision integers Fixed point numbers C++ user-defined types Event-driven simulation Kernel C++ Language Standard B. Miramond - UCP Architecture de SystemC User Applications Methodology Specific Libraries Standard Channels Kahn Process Network, Static Dataflow, Dataflow, Etc. Master/Slave Library, etc. Elementary Channels Signal, Timer, Mutex, FIFO… Core Language Data-Types Modules Ports Processes Events Interfaces Channels 4-valued logic types (O1XZ) 4valued logic vectors Bits and bit-vectors Arbitrary-precision integers Fixed point numbers C++ user-defined types Event-driven simulation Kernel C++ Language Standard WorkStation Environment B. Miramond - UCP SystemC Standard Compilation d’un projet SystemC g++ -I$ (SYSTEMC) /include \ -L$ (SYSTEMC) /lib-$ (ARCH) –lsystemc \ $(SRC) systemc Le résultat contient à la fois votre code applicatif et le code de la machine de simulation SystemC !! File1.h File1.cpp … Filen.h Filen.cpp systemc.h g++ File1.o … Filen.o B. Miramond - UCP STL … ld .exe 2. Structures Processes (Concurrency) Modules (Structure) Channels (Communication) Séparées Events (time, synchronisation) Port (Structure) Data types (Hardware, Fonctionnalité Communication Interfaces (Communication / Traitement refinement) fixed point) Port Module Process 1 Module Channel Interface B. Miramond - UCP P2 P3 a. Modules sc_module Un module est un conteneur (container). Il contient : Des ports qui permettent de communiquer avec d’autres modules Des processus qui décrivent la fonctionnalité du module Des données internes représentant l’état et des canaux internes pour la communication entre les processus du module Et hiérarchiquement, d’autres modules B. Miramond - UCP Déclaration par la macro SC_MODULE class Adder : public sc_module { // Ports, processes, internal data … Adder (sc_module_name name, int other_param) : sc_module(name){ // Body of constructor : // Process declaration, sensitivities } }; Cette déclaration crée une nouvelle classe d’objets de type Adder. Les définition sont réalisées dans des fichier .CPP. Les déclaration dans des fichiers .H B. Miramond - UCP Instanciation de SC_MODULE Les SC_MODULE peuvent être instanciés lors de la phase d’élaboration uniquement (cf. section III) En précisant un nom de module Avec la syntaxe suivante : Adder MyAdder(‘’MyAdder’’); B. Miramond - UCP 3. Interfaces, Ports et channels En modélisation matériel classique (RTL), le signal est le moyen de communication entre processus. Au niveau système, le moyen de communication n’a pas encore d’implantation établie (bus Hw, appel de service logiciel comme FIFO, mutex…). SystemC offre cette flexibilité par la séparation entre Les canaux qui sont le moyen de transmission des données Les interfaces qui fournissent les prototypes des services d’accès au canal Les ports qui sont une instanciation des interfaces dans un module client. B. Miramond - UCP a. Interfaces Un canal exporte son interface à travers la classe abstraite sc_interface. L’interface spécifie donc uniquement la signature (le prototype) des opérations/services fournies par son canal. Rappel : Les sc_interface sont des classes templates C++. Une classe template permet de paramétrer le type des données qu’elle manipule en placant le type entre ‘<T>’. B. Miramond - UCP Exemple sc_signal_in_if<T> Dérive directement de sc_interface et est paramétrée par le type T. Elle ne fournit qu’un seul service : read() qui retourne une référence à la valeur de type T. sc_signal_inout_if<T> Celle-ci fournit en plus une fonction virtuelle write() qui prend en paramètre la valeur à placer. Cette seconde interface dérive de sc_signal_in_if et hérite donc de la fonction read(). B. Miramond - UCP sc_interface register_port() (virtual) sc_signal_in_if<T> read() sc_signal_inout_if<T> write() B. Miramond - UCP class sc_signal_in_if : virtual public sc_interface { public : virtual const T& read() = 0; } sc_signal est utilisé pour la communication à l’intérieur d’un module entre processus. Built-in primitive Channels sc_signal<int> S1, S2; sc_buffer<T> B; sc_fifo<T> F; sc_mutex M; sc_semaphore P(1); S1.write(S2.read()); // déclaration // Affectation B. Miramond - UCP b. Ports Les ports sont utilisés comme déclaration de connexion à un canal via son interface. La déclaration doit spécifier l’interface à laquelle il correspond. Déclaration sc_port<sc_signal_inout_if<int> > p; p->read(); p->write(); Ceci est un exemple d’IMC (Interface Method Call). B. Miramond - UCP Ports prédéfinis dans SystemC Template <class T> class sc_in : public sc_port<sc_signal_in_if<T> > …; Template <class T> class sc_inout : public sc_port<sc_signal_inout_if<T> > …; B. Miramond - UCP Exemple (suite) Adder class Adder : public sc_module { // Ports, processes, internal data … sc_in <int> a; sc_in <int> b; sc_in <int> c; Adder (sc_module_name name, int other_param) : sc_module(name){ // Body of constructor : // Process declaration, sensitivities } }; La déclaration des ports doit intervenir en premier dans le module!! Et l’ordre a une importance. B. Miramond - UCP c. Channels sc_channel Alors que les ports et interfaces définissent quelles fonctions sont disponibles, le canal décrit l’implémentation de ces fonctions. Tous les canaux héritent de sc_prime_channel. La classe canal doit gérer les accès multiples (tel que sur un bus). Ses méthodes d’accès suivent un schéma dit : Request-Update B. Miramond - UCP d. Hierarchical Channels Plusieurs canaux peuvent implémenter la même interface. Ainsi, un ‘primitive channel’ ne contient pas d’autres structures SystemC (modules, process…). Au contraire, il est parfois nécessaire de modéliser des structures de communication plus complexes : Le standard OCB = On-Chip Bus de VSIA : Arbitrer Control Program Unit Decoder Unit L’avantage des ports et interfaces est donc clair, ils permettent de découpler l’interface de son implémentation et donc de raffiner les communications (par ex.) d’un B.canal simple à un canal hiérarchique. Miramond - UCP 4. Processus Process La nature parallèle des systèmes électronique nécessite la description de fonctionnalités concurrentes. A process SystemC doit être contenu dans un module. Le code associé au process doit être une fonction membre du SC_MODULE Les processus accèdent aux canaux extérieurs par l’intermédiaire des ports de leur module. B. Miramond - UCP Exemple (suite) Adder class Adder : public sc_module { // Ports, processes, internal data … sc_in <int> a; sc_in <int> b; sc_out<int> c; void compute (){ c = a + b; } SC_HAS_PROCESS(Adder); Adder (sc_module_name name, int other_param) : sc_module(name){ // Process declaration, sensitivities SC_METHOD(compute); sensitive << a << b; } }; B. Miramond - UCP Pièges Le fait de déclarer une nouvelle méthode dans un SC_MODULE ne fait pas d’elle un process. C’est l’appel à SC_METHOD qui enregistre la méthode en paramètre auprès du scheduler de SystemC. Cet enregistrement (l’appel à SC_METHOD) ne peut être fait qu’à la phase d’élaboration, pas pendant la simulation. Les SC_METHOD ne peuvent être intérrompus, il ne doivent donc pas contenir de boucle infinies !! B. Miramond - UCP Plusieurs sortes de process SC_METHOD() SC_THREAD() Processus ne pouvant être interrompus (ils ne peuvent appelé wait()) Le code doit être fonction membre d’un SC_MODULE Le plus rapide à la simulation. Processus pouvant être interrompus (par wait) Ses variables sont persistantes (contrairement au SC_METHOD) Le code n’est pas nécessairement fonction membre du module sc_spawn() // cf. Chapitres suivants Autorise la création dynamique de processus, donc après la phase d’élaboration. Le code n’est pas nécessairement fonction membre du module B. Miramond - UCP Structure of a process SC_METHOD : simulation engine call them repeatedly void my_process (){ // run to completion scheme // treatment } SC_THREAD : void my_thread(){ // infinite loop scheme while (1){ // treatment wait(); // static event } } B. Miramond - UCP 5. Events Un processus dispose d’une liste de sensibilité décrivant les événements auxquels il doit réagir. Lorsque l’exécution d’un processus rencontre un wait(), il est interrompu. Il attend le déclenchement (implicite) d’un des évènements de sa liste de sensibilité statique. Lorsqu’un de ses événements est déclenché, le scheduler place le Thread dans la liste des processus READY. B. Miramond - UCP a. sc_event Un event est un objet de classe sc_event. Il n’a ni durée, ni valeur. L’acte d’indiquer une modification d’un évènement est appelé notification. sc_event e; e.notify(); notify(e); L’évènement garde une liste des processus qui lui sont sensibles (par wait(e)). Lorsque un event est notifié, il informe le scheduler des processus à (re)lancer. B. Miramond - UCP b. Notification Immediate : e.notify(); Delta_delay : e.notify(SC_ZERO_TIME); Notification immédiate, le processus en attente est replacé immédiatement dans la liste Ready Notification après un cycle d’évaluation appelé Delta-cycle, lorsque tous les processus en attente se seront exécutés. Non-zero delay : e.notify(t); Place l’évènement en fil d’attente jusqu’à la durée indiquée. B. Miramond - UCP 6. Sensitivity a. Sensibilité statique = La liste des évènements d’activation d’un process est déterminé avant la simulation (dans les constructeurs). sensitive << a << b; b. Sensibilité dynamique = Permet de remplacer la liste statique par un évènement désigné lors de la simulation. Le processus n’est alors plus sensible aux évènements de sa liste statique. wait(e); B. Miramond - UCP Exemple (suite) class Adder : public sc_module { // Ports, processes, internal data … sc_in <int> a; sc_in <int> b; sc_out<int> c; Adder Cas particulier : Ici a et b sont des sc_ports. void compute (){ La sensibilité se fait par c = a + b; l’intérmédiaire de la } fonction default_event SC_HAS_PROCESS(Adder); associée. Adder (sc_module_name name) : sc_module(name){ // Process declaration, sensitivities SC_METHOD(compute); sensitive << a << b; } }; B. Miramond - UCP c. Composition d’évènements Conjonction : wait (e1 & e2 & e3); ou wait (timeout | e1 | e2); Activation si les 3 event sont déclenchés Disjonction : wait(e1 | e2 | e3); ou wait (timeout | e1 | e2); Activation si 1 des 3 event est déclenché ou bien un timeout Il n’est pas possible de savoir quel événement a provoqué le déclenchement. Par contre il est possible de savoir si c’est le timeout : wait(t_Delay | ack_event | bus_error_event); if (timed_out()) … // action associated to timeout B. Miramond - UCP d. Attente d’un TimeOut Attente de 200 nanosecondes : wait(200, SC_NS); Ou bien sc_time t(200, SC_NS); wait(t); Attente d’un Delta-cycle : wait(0); Combinaisons event(s) | timeout: wait(200, SC_NS, e); B. Miramond - UCP 7. Final Example A la manière des classes et des objets, les modèles sont à opposés aux instances (de modules et de canaux) en SystemC comme en HDL. Exemple hiérarchique : in1 in2 Adder1 sum Adder2 in3 Add3 B. Miramond - UCP class Add3 : public sc_module { sc_in<int> in1; sc_in<int> in2; sc_in<int> in3; sc_out<int> sum; in1 in2 sum Adder2 in3 Add3 // signal (channel) interne sc_signal<int> Adder1 temp temp; Adder* adder1; Adder* adder2; Add3(sc_name name) : sc_module(name){ adder 1 = new Adder(‘’Adder1’’); (*adder1)(in1, in2, temp); // Connectique forme positionnelle adder 2 = new Adder(‘’Adder2’’); adder2->a(temp); adder2->c(sum); adder2->b(in3); // Connectique forme nommée // Pas d’ordre imposé } } B. Miramond - UCP int sc_main(int argc, char* argv[]){ // initialisation // simulation top_level(); // Nettoyage des structures return 0; } temp in1 in2 Adder1 sum Adder2 in3 Add3 top_level(){ sc_signal <int> sig_a, sig_b, sig_c; Add3 my_adder(‘’my_adder’’); //Autres modules et tesbenchs qui positionnent // les valeurs de sig_a et sig_b //Lance la phase d’Elaboration puis celle de Simulation //Exécution durant 1000 secondes (de temps de simulation) sc_start(1000, SC_SEC); //Suite de la simulation pendant 100 ms sc_start(100, SC_MS); } B. Miramond - UCP 8. Debugging #include “systemc.h“ Class nand2 : public sc_module { sc_port<sc_signal_in_if<bool>, 1> A; sc_in<bool> B; sc_out<bool> F; A //input signal port //other writing //output signal port void do_nand2(){ F.write( !(A.read() && b.read()) ); } SC_HAS_PROCESS(nand2); nand2 (sc_name name) : sc_module(name){ // Constructor SC_METHOD(do_nand2);// register do_nand2 with scheduler sensitive << A << B; } }; B. Miramond - UCP B F 2-input xor F = A ⊕ B = ( A + B).( A + B ) A S2 F S1 S3 B B. Miramond - UCP #include “systemc.h“ #include “nand2.h“ … xor2(sc_name name) : n1(‘N1’), n2(‘N2’), n3(‘N3’), n4(‘N4’) class xor2 : public sc_module { { n1.A(A); sc_in<bool> A, B; n1.B(B); sc_out<bool> F; n1.F(S1); nand2 n1, n2, n3, n4; (*n2)(A, S1, S2); sc_signal<bool> S1, S2, S3; … n3.A(S1); n3.B(B); n3.F(S3); A n4.A(S2); n4.B(S3); n4.F(F); S2 F S1 S3 } B }; B. Miramond - UCP a. Debug Environnement xor2 A A S2 Stimuli Generator F S1 Monitor S3 B B Clock B. Miramond - UCP CK #include ‘’systemc.h’’ class stim : public sc_module{ sc_out<bool> A, B; sc_in_clk Clk; void StimGen(){ A.write(false); B.write(false); wait(); A.write(false); B.write(true); wait(); A.write(true); B.write(false); wait(); A.write(true); B.write(true); wait(); sc_stop(); } SC_HAS_PROCESS(stim); stim(sc_name name) : sc_module(name){ SC_THREAD(StimGen); sensitive << Clk.pos(); } }; #include ‘systemc.h’ #include <iomanip.h> class monitor : public sc_module{ sc_in<bool> A,B, F; sc_in<bool> Clk; void do_monitor(){ cout << setw(10) << ‘time’; cout << setw(2) << ‘A’; // … while(true){ cout << setw(10) << sc_time_stamp(); cout << setw(2) << A.read(); // … wait(); } } SC_HAS_PROCESS(monitor); monitor(sc_name name) : sc_module(name){ SC_THREAD(monitor): sensitive << Clk.pos(); } }; B. Miramond - UCP b. Testbench results #include ‘systemc.h’ #include ‘stim.h’ #include ‘exor2.h’ #include ‘mon.h’ int sc_main (…){ sc_signal<bool> ASig, BSig, FSig; sc_clock TestClk(‘TestCk’, 10, SC_NS, 0,5); stim Stim1(‘Stimulus’); exor2 DUT(‘exor2’); monitor Monitor1(‘Monitor’); Time A B F ,,,,,,1 ns 0 0 0 11 ns 0 0 0 21 ns 0 1 1 31 ns 1 0 1 41 ns 1 1 0 // Connection with ASig, BSig et FSig sc_start(); // run forever return 0; } B. Miramond - UCP #include ‘systemc.h’ #include ‘stim.h’ #include ‘exor2.h’ #include ‘mon.h’ c. Waveform tracing int sc_main(int argc, char *argv[]){ sc_signal<bool> ASig, BSig, FSig; sc_clock TestClk(‘TestClock’, 10, SC_NS, 0,5, 1, SC_NS); … instance of stim exor2 DUT(‘exor2’); DUT.A(ASig); DUT.B(BSig); DUT.F(FSig); … instance of monitor •Declare the trace sc_trace_file* Tf; Tf = sc_create_vcd_trace_file(‘traces’); Tf->set_time_unit(1, SC_NS); •(optional : specify the trace time unit) //deprecated : //((vcd_trace_file*)Tf)->sc_set_vcd_time_unit(-9); sc_trace(Tf, ASig, ‘A’); sc_trace(Tf, BSig, ‘B’); sc_trace(Tf, FSig, ‘F’); sc_trace(Tf, DUT.S1, ‘S1’); sc_trace(Tf, DUT.S2, ‘S2’); sc_trace(Tf, DUT.S3, ‘S3’); sc_start(); sc_close_vcd_trace_file(Tf); return 0; •Create trace file •Register signals or variables for tracing (even hierarchically : DUT.S1) // DUT = Design Under Test •Run the simulation •Close the trace file B. Miramond - UCP d. Resulting waveforms B. Miramond - UCP III. Simulation Kernel B. Miramond - UCP Concurrence simulée L’objectif du scheduler SystemC est de simuler l’exécution parallèle de la plateforme matérielle décrite bien que la simulation tourne sur une station de travail mono-processeur. La concurrence simulée en SystemC n’est pas préemptive, c’est le code de chaque processus qui redonne la main au scheduler (wait). B. Miramond - UCP Section organisation Time management SystemC scheduler SystemC scheduling steps 1. 2. 3. 1. 2. 3. 4. 5. 6. The case of Channels : Evaluate-update Concurrency and time 4. 5. 1. 2. 3. 6. Delayed notification Timed notification Immediate notification Simulation steps synthesis Dont_intialize ! Ending simuation Perceived concurrency Zero-time execution Scheduled concurrency Event-driven simulators (not yet) B. Miramond - UCP 1. Gestion du temps a) sc_time Le simulateur SystemC est discret. Il utilise un quantum de temps minimal qui peut être définit par sc_set_time_resolution(int, sc_time_unit) Par défaut, la plus petite résolution du temps est 1 picoseconde (10-12s) SystemC définit un type énuméré des unités de temps, sc_time_unit : SC_FS SC_PS SC_NS SC_US SC_MS SC_SEC femtoseconde picoseonde nanoseconde microseconde milliseconde (10-15s) (10-12s) (10-9s) (10-6s) (10-3s) B. Miramond - UCP Default SC_TIME sc_time est le type utilisé pour déclarer des variables de temps Déclaration : sc_time t1(42, SC_PS); sc_time sc_time_stamp() retourne le temps courant de simulation double sc_simulation_time() retourne le temps courant de simulation en unité de temps par défaut B. Miramond - UCP b) Déclaration d’horloges : sc_clock Utilisées pour la synchronisation Les arguments sont : Un label, La période de l’horloge : valeur + unité Le temps passé à l’état haut La date du premier front Et un booléen indiquant si le premier front est montant ou descendant. sc_clock(« Clk », 1, SC_NS); sc_clock(« Clk », 1, SC_NS, 0.5, 0, SC_NS, true); B. Miramond - UCP Services de l’horloge En SystemC les horloges sont des canaux hiérarchiques, Ils offrent les services suivants : period(); // returns sc_time duty_cycle(); // returns a double (fraction of the period) posedge(); // returns a reference to the positive clock edge; negedge(); // negative… read(); // return the current value event(); // detects if there has been a change on clock posedge_event(); // returns an event notification for pos clock edge negedge_event(); // returns an event notification for neg clock edge B. Miramond - UCP Ports dédiés Un module peut utiliser les ports dédiés de l’horloge pour pouvoir être synchrone : sc_in_clock sc_out_clock sc_inout_clock Les horloges ne sont lancées qu’après l’appel à sc_start() Ce ne sont rien de plus que des sc_in<bool> Mais ils fournissent les méthodes pos() et neg() qui font appel à pos_edge_event() et neg_edge_event() B. Miramond - UCP 2. Scheduler SystemC Le séquencement des opération réalisé par SystemC est Déterministe : l’ordre des opérations sera toujours le même dans les même conditions Mais l’utilisateur n’a pas de moyen de connaître ce séquencement à l’avance Il est donc déconseillé de faire communiquer 2 processus par variable partagé globale, car l’ordre de lecture/écriture n’est pas spécifié. B. Miramond - UCP sc_main() 3. Simulation steps SystemC Simulation Kernel .notify(); // immediate Elaboration sc_start(); Initialize Evaluate ∆ Advance Time while process ready Cleanup .notify(SC_ZERO_TIME); // delayed B. Miramond - UCP .notify(t); // timed Simulation steps Elaboration Initialisation Les processus sont exécutés en fonction de leur sensibilité Advance time Débute après l’appel à sc_start() Les processus créées à l’élaboration sont lancés. Tous les processus sont placés dans la file READY. Evaluate-Update Les modules SystemC sont construits Les SC_METHOD et SC_THREAD sont créées. Time management Cleanup Clean objects and structures B. Miramond - UCP Rappel Seul les SC_THREAD font des appels à wait() Ils ne sont exécutés qu’une seule fois, mais peuvent être interrompus. Tous les SC_METHOD ont une liste statique et sont re-déclenché à chaque nouvelle notification. Ils sont exécutés autant de fois que nécessaire. B. Miramond - UCP Files d’attente duDurant scheduler son exécution, un processus peut réaliser des a. Delayed notification notifications qui réveillent d’autres Ready Running P1 P4 P2 P3 processus en attente (Waiting). Events Waiting P5 E1@0 P6 E2@t1 E3@t2 Un par un, les processus sont pris aléatoirement de la fileDelta-cycle Ready et désignés Après un comme Running jusqu’à rencontrer un wait() ou un return(). B. Miramond - UCP E4@() sc_main() Elaboration sc_start(); Simulation steps SystemC Simulation Kernel Les processus attendant un événement notifié avec un délai SC_ZERO_TIME(.notify(0)) sont replacés dans la file Ready au prochain cycle de simulation. Ce cycle est appelé Delta-Cycle Delay. Initialize Evaluate ∆ Cleanup .notify(SC_ZERO_TIME); // delayed B. Miramond - UCP Advance Time while process ready b. Timed notification Events Ready Running Waiting P1 P4 P5 E1@0 P6 E2@t1 E3@t2 P2 P3 E4@() Après un temps t1 B. Miramond - UCP sc_main() Elaboration sc_start(); Simulation steps SystemC Simulation Kernel Les processus attendant un événement notifié avec un délai non-nul sont placés dans la file Waiting et le temps est avancé jusqu’au temps du premier événement de la liste. A cet instant les processus en attente sont placés en file Ready. Initialize Evaluate ∆ Advance Time while process ready Cleanup .notify(t); // timed B. Miramond - UCP c. Immediate notification Events Ready Running Waiting P1 P4 P5 E1@0 P6 E2@t1 E3@t2 P2 P3 E4@() Dans le même cycle B. Miramond - UCP sc_main() Simulation steps SystemC Simulation Kernel .notify(); // immediate Elaboration sc_start(); Initialize Evaluate ∆ Cleanup Advance Time while process ready Une notification immédiate place directement les processus en attente durant le même delta-cycle. Ceci peut se produire plusieurs fois jusqu’à rencontré une notification timée. B. Miramond - UCP d. Synthèse des étapes de simulation du scheduler SystemC 1. 2. 3. 4. 5. 6. 7. 8. Initialisation Evaluation S’il y a encore des processus prèt, retour en 2 Update S’il y a eu des notifications Delta-cyle, déterminer les processus READY et retour en 2. S’il n’y a plus de ‘non-Zero notifications’, la simulation est terminée Sinon, avancer le temps au prochain temps de notification Déterminer les processus READY, retour en 2. B. Miramond - UCP e. La fonction dont_initialize() Normallement tous les processus sont exécutés la première fois durant la phase d’initialisation. SystemC permet de spécifier que certains processus ne seront pas exécutés à cette phase : SC_METHOD(waiting_method) sensitive << a << b; dont_initialize(); La fonction nécessite une liste de sensibilité statique !! Sinon, le processus ne sera pas démarré. B. Miramond - UCP f. End of simulation 1. 2. 3. sc_start(argument); // where argument precise the amount of simulation time. Only used with timed models !! sc_stop(); // inside a component. It terminates simulation when a specified functional condition is atteined. Too local ! Terminator module, which call the sc_stop() primitive only when the logical sum of products on the endproces boolean condition is true. Global untimed halt condition. B. Miramond - UCP 4) Le cas des channels : evaluate-update Les canaux simples utilisent une procédure de mise à jour particulière appelée : request_update/update scheme. Ce schéma permet de construire des canaux supportant des changements d’état intervenant sur des durées infinitésimales (∆Cycle) et donc d’exprimer la concurrence à son niveau le plus précis. B. Miramond - UCP Exemple 1 On cherche à swapper la valeur présente dans 2 registres au moment de l’horloge. Si on modélise les registres par des variables, il est nécessaire d’utiliser une 3e variable temporaire pour faire le swap. Si on utilise des signaux, 2 sont suffisants car l’écriture et la lecture ne se font pas dans le même cycle. B. Miramond - UCP Exemple 2 Q2 Q1 DATA D Reg3 Reg2 Reg1 Q D SYNC Comportement attendu : 2. Q4 = Q3 3. Q3 = Q2 4. Q2 = Q1 5. Q1 = DATA Reg4 Q3 D Q Q Q4 D Q Pour que la fonctionnalité soit respectée, L’ordre est important Chaque registre est un processus indépendant. Or le simulateur ne précise aucun ordre sur les processus. B. Miramond - UCP Solution : 2 données du canal ‘Signal’ Chaque signal a deux lieux de mémorisation : New value Et current value Lors d’une écriture, 3. le signal place la valeur dans ‘New value’ 4. Puis le processus appelle request_update() pour que le simulateur appelle à son tour la fonction update() du canal lors de la prochaine phase. 5. Lorsque la phase d’évaluation est réellement terminée (il n’y a plus de processus en état Ready), le simulateur appelle update() pour chaque canal ayant fait un appel à request_update(). 6. Le canal recopie la nouvelle valeur et notifie un sc_event pour indiquer un changement de valeur. Donc si un process écrit sur un signal et lit immédiatement, il trouvera la valeur inchangé !! B. Miramond - UCP New/Current value Delta-Cycle New Value Canaux Current Value S1 = V2 S1= V0 S2 = V3 S2= V1 Update() B. Miramond - UCP The Update Simulation step sc_main() SystemC Simulation Kernel Elaboration sc_start(); Initialize Evaluate ∆ Cleanup Update B. Miramond - UCP Advance Time Exemple // Declaration Int count; sc_string message_tmp; sc_signal<int> count_sig; sc_signal<sc_string> message_sig; // Intializing during first delta cycle count_sig.write(10); message_sig.write(‘Hello’); count = 11; message_temp = ‘Bonjour’; print_state(count, count_sig, message_temp, message_sig); wait(SC_ZERO_TIME); // 2nd delta cycle count = 20; count_sig.write(count); print_state(count, count_sig, message_temp, message_sig); wait(SC_ZERO_TIME); // 3rd delta cycle message_sig.write(message_temp = ‘New message’); print_state(count, count_sig, message_temp, message_sig); B. Miramond - UCP // Konsole // First delta cycle count is count_sig is message_temp is message_sig is // 2nd delta cycle count is count_sig is message_temp is message_sig is // 3rd delta cycle count is count_sig is message_temp is message_sig is 11 0 Bonjour ‘’ 20 10 Bonjour Hello 20 20 New Message Hello Guide d’utilisation Pour bien utiliser ces canaux : 1. 2. 3. 4. Utiliser comme convention de nommage pour les signaux avec le suffixe _sig Lire tous les ports et signaux dans une variable locale Réaliser les traitements sur ces variables locales Écrire le résultat sur les ports et les signaux Concept proche d’un automate de Moore… B. Miramond - UCP Résumé du schéma request_update/update Ce schéma correspond à dire que la mise à jour de ces signaux est retardée d’un Delta-cycle. Ce schéma ne s’applique qu’aux canaux primitifs, mais pas à tous : sc_signal sc_fifo mais pas sc_mutex et sc_semaphore (cf. section IV) B. Miramond - UCP 5) Concurrence et évolution du temps Process A(){ // @ t0 codeA1; codeA2; wait(t1); codeA3; codeA4; wait(t2); codeA5; codeA6; wait(t3); } Process B(){ // @ t0 codeB1; codeB2; wait(t1); codeB3; codeB4; wait(t2); codeB5; codeB6; wait(t3); } Process C(){ // @ t0 codeC1; codeC2; wait(t1); codeC3; codeC4; wait(t2); codeC5; codeC6; wait(t3); } B. Miramond - UCP Process D(){ // @ t0 codeD1; codeD2; wait(t1); codeD3; wait(0); codeD4; wait(t3); } Activité perçue lors de la simulation A B A1; A2; A3; A4; A5; 16; B1; B2; B3; B4; B5; B6; C1; C2; C3; C4; C5; C6; D1; D2; D3; D4; … C D t1 t2 B. Miramond - UCP t3 Activité réelle lors de la simulation (1) A B C A3; A4; A1; A2; A5; 16; Chaque portion de code est exécutée en temps nul !!! B1; B2; B3; B4; B5; B6; C1; C2; C3; C4; C5; C6; D1; D2; D3; D4; … Ce sont les wait(t) qui font avancer le temps ! D t1 t2 B. Miramond - UCP t3 Activité réelle lors de la simulation (2) A1; A2; A3; A4; A B C1; C2; A1; A2; Les opérations qui apparaissent concurrentes à l’utilisateur sont séquencées B5; B6; par le B1;scheduler B2; SystemC. Cet ordre est déterministe mais non prévisible ! B3; B4; B1; B2; A5; 16; C5; C6; C3; C4; C1; C2; C D1; D2; D1; D2; D4; D Rq: Extansion du temps t1 t2 B. Miramond - UCP t3 6. Event-based simulators VHDL, Verilog … B. Miramond - UCP End of Green B. Miramond - UCP