用openmp实现AES加密的电路级并行仿真

时间:2013-11-20 21:27:22

标签: c performance aes openmp simulation

我正在尝试并行化C / C ++中的翻译程序。该程序最初采用Verilog硬件描述语言。该程序已由翻译程序翻译成C / C ++。它是电路级C / C ++程序的事实不应该有所作为。我基本上试图遵循

中的方法

https://stackoverflow.com/users/2979872/user2979872

但是

当我尝试使用openmp进行并行化时,我得到了一个SEGMENTATION FAULT。这是代码。当我通过编写#pragma omp parallel num_threads(2)private(top)来制作“top”,这是指向私有对象的指针时,我得到了分段错误。

/////////////////////////////////////////////// ///////////////////////////////////////////

int main(int argc, char **argv, char **env)
{
      Verilated::commandArgs(argc, argv);
      Vaes_cipher_top* top = new Vaes_cipher_top; // this is the aes object that will do the enc
      unsigned int i = 0;
      unsigned int set_done;
      unsigned int ld_set = 0;
      top->rst = 1;           // assert reset

      #pragma omp parallel num_threads(2) private(top)
       while (i < 2)
        {
              if (main_time > 10)
              {
              top->rst = 0;   // Deassert reset
              }
          if ((main_time % 10) == 1)
          {
              top->clk = 1;       // Toggle clock (posedge)
          }
          if ((main_time % 10) == 6)
          {

              top->clk = 0;
              //setting DUT values

             if(ld_set!=1 && main_time > 10)
              {
                    top -> ld = 1;
                    top -> key     =   {0x00000000,0x00000000,0x00000000,0x00000000};
                    top -> text_in =   {0x00000000,0x00000000,0x00000000,0x00000000};
                    ld_set++;
               }
              else if(ld_set == 1 && main_time > 10)
               {
                top -> ld = 0;
                 set_done = 0;
                }

            } //(main_time % 10) == 6)

            top->eval();            // Evaluate model

            if(top->done && !set_done)
            {

             print(top->key);
             print(top->text_in);
             print(top->text_out);
             ld_set = 0; //reset  
             i++;
             set_done  = 1;
            } //if(top->done)

            main_time++;            // Time passes...
        } //end of while 

        printf("\n Test Done\n");
        top->final();               // Done simulating

 delete top;

 return 0;
} //end of main

按照Hristo的建议,努力向前迈进。没有更多的分段错误,但由于竞争条件导致错误的结果。

 int main(int argc, char **argv, char **env)
{
  Verilated::commandArgs(argc, argv);
  Vaes_cipher_top* top;  // this is the aes object that will do the enc
  unsigned int i = 0;
  unsigned int set_done;
  unsigned int ld_set = 0;
  //top->rst = 1;           // assert reset
  unsigned int iter_count = 1;

  #pragma omp parallel num_threads(2) firstprivate(iter_count,ld_set,set_done,i)
   while (i < 2)
    {
         if(iter_count)
          {
          top = new Vaes_cipher_top;
          iter_count = 0; 
          }
          if(main_time == 0)
            top-> rst = 1;  //assert reset
          if (main_time > 10)
          {
          top->rst = 0;   // Deassert reset
          }
      if ((main_time % 10) == 1)
      {
          top->clk = 1;       // Toggle clock (posedge)
      }
      if ((main_time % 10) == 6)
      {

          top->clk = 0;
          //setting DUT values

         if(ld_set!=1 && main_time > 10)
          {
                top -> ld = 1;
                top -> key     =   {0x00000000,0x00000000,0x00000000,0x00000000};
                top -> text_in =   {0x00000000,0x00000000,0x00000000,0x00000000};
                ld_set++;
           }
          else if(ld_set == 1 && main_time > 10)
           {
            top -> ld = 0;
             set_done = 0;
            }

        } //(main_time % 10) == 6)

        top->eval();            // Evaluate model

        if(top->done && !set_done)
        {

         print(top->key);
         print(top->text_in);
         print(top->text_out);
         ld_set = 0; //reset  
         i++;
         set_done  = 1;
         iter_count = 1; 
        } //if(top->done)

        main_time++;            // Time passes...
    } //end of while 

    printf("\n Test Done\n");
    top->final();               // Done simulating

     delete top;

return 0;
} //end of main

/////////////////////////////////////////////// /////////////////////////////////////

根据Hristo的建议更新,以便在while循环中移动声明Vaes_cipher_top * top

int main(int argc, char **argv, char **env)
 {
  Verilated::commandArgs(argc, argv);
  unsigned int i = 0;
  unsigned int set_done;
  unsigned int ld_set = 0;
  //top->rst = 1;           // assert reset
  unsigned int iter_count = 1;

  #pragma omp parallel num_threads(2) firstprivate(iter_count,ld_set,set_done,i)
   while (i < 2)
    {
         if(iter_count)
          {
          Vaes_cipher_top* top;  // this is the aes object that will do the enc
          top = new Vaes_cipher_top;
          iter_count = 0; 
          }
          if(main_time == 0)
            top-> rst = 1;  //assert reset
          if (main_time > 10)
          {
          top->rst = 0;   // Deassert reset
          }
      if ((main_time % 10) == 1)
      {
          top->clk = 1;       // Toggle clock (posedge)
      }
      if ((main_time % 10) == 6)
      {

          top->clk = 0;
          //setting DUT values

         if(ld_set!=1 && main_time > 10)
          {
                top -> ld = 1;
                top -> key     =   {0x00000000,0x00000000,0x00000000,0x00000000};
                top -> text_in =   {0x00000000,0x00000000,0x00000000,0x00000000};
                ld_set++;
           }
          else if(ld_set == 1 && main_time > 10)
           {
            top -> ld = 0;
             set_done = 0;
            }

        } //(main_time % 10) == 6)

        top->eval();            // Evaluate model

        if(top->done && !set_done)
        {

         print(top->key);
         print(top->text_in);
         print(top->text_out);
         ld_set = 0; //reset  
         i++;
         set_done  = 1;
         iter_count = 1; 
        } //if(top->done)

        main_time++;            // Time passes...
    } //end of while 

    printf("\n Test Done\n");
    top->final();               // Done simulating

     delete top;

return 0;
} //end of main

/////////////////////////////////////////////// ///////////////////////////////////////////// 这是输出。所有错误都是一样的。我正在提出一些

./ sim_main.cpp:76:错误:此范围内未声明'top'(在top-&gt; rst = 1的行) ../sim_main.cpp:80:错误:'top'未在此范围内声明(在top-&gt; rst = 0的行上) ../sim_main.cpp:84:错误:在此范围内未声明'top'(在top-&gt; clk = 1的行上) ../sim_main.cpp:89:错误:在此范围内未声明'top'(在top-&gt; clk = 0的行上)

如果删除围绕Vaes_cipher_top声明的if,它将变为无限循环! ////////////////////////////////////////////////// /////////////////////////////////////////

模拟挂起和输出在每次运行的不同时间出现。我使用2个线程,即num_threads(2)

    (1) This is the run where simulation terminates

key=67fd3c2821b9201521d6a87f205e3039
text_in=67fd3c2821b9201521d6a87f205e3039
Time=251,text_out=71a354729996bac975784dcdb50260d9, done= 1 on  0 of  2
i= 1
key=1a857b7f39a0290d20bbf2466b5b14e8
text_in=1a857b7f39a0290d20bbf2466b5b14e8
Time=321,text_out=da36095f53fd86a57f9d147e8e05603, done= 1 on  1 of  2
i= 1
key=67fd3c2821b9201521d6a87f205e3039
text_in=67fd3c2821b9201521d6a87f205e3039
Time=401,text_out=71a354729996bac975784dcdb50260d9, done= 1 on  0 of  2
i= 2
key=1a857b7f39a0290d20bbf2466b5b14e8
text_in=1a857b7f39a0290d20bbf2466b5b14e8
Time=601,text_out=da36095f53fd86a57f9d147e8e05603, done= 1 on  1 of  2
i= 2
key=67fd3c2821b9201521d6a87f205e3039
text_in=67fd3c2821b9201521d6a87f205e3039
Time=641,text_out=71a354729996bac975784dcdb50260d9, done= 1 on  0 of  2
i= 3
key=1a857b7f39a0290d20bbf2466b5b14e8
text_in=1a857b7f39a0290d20bbf2466b5b14e8
Time=841,text_out=da36095f53fd86a57f9d147e8e05603, done= 1 on  1 of  2
i= 3
key=67fd3c2821b9201521d6a87f205e3039
text_in=67fd3c2821b9201521d6a87f205e3039
Time=911,text_out=71a354729996bac975784dcdb50260d9, done= 1 on  0 of  2
i= 4
key=1a857b7f39a0290d20bbf2466b5b14e8
text_in=1a857b7f39a0290d20bbf2466b5b14e8
Time=991,text_out=da36095f53fd86a57f9d147e8e05603, done= 1 on  1 of  2
i= 4

 Test Done

    (2) This is the RUN where simulation DOES NOT terminate and i had to press ctrl+c   
        to abort the simulation

    key=75f1bcf47451ab0f33b58a5e1adfdd6
text_in=75f1bcf47451ab0f33b58a5e1adfdd6
Time=411,text_out=9049c33819d61de5c09aa388479ef10, done= 1 on  0 of  2
i= 1
key=75f1bcf47451ab0f33b58a5e1adfdd6
text_in=75f1bcf47451ab0f33b58a5e1adfdd6
Time=696,text_out=9049c33819d61de5c09aa388479ef10, done= 1 on  0 of  2
i= 2
key=75f1bcf47451ab0f33b58a5e1adfdd6
text_in=75f1bcf47451ab0f33b58a5e1adfdd6
Time=931,text_out=9049c33819d61de5c09aa388479ef10, done= 1 on  0 of  2
i= 3
key=75f1bcf47451ab0f33b58a5e1adfdd6
text_in=75f1bcf47451ab0f33b58a5e1adfdd6
Time=1151,text_out=9049c33819d61de5c09aa388479ef10, done= 1 on  0 of  2
i= 4
^C 

(必须按Ctrl + c才能中止模拟。只使用1个核心代替 2,为什么会发生这种情况以及如何防止这种情况发生?为什么输出
两个线程没有同时出现?可以这样做吗?

请点击按钮 添加/显示1条评论 在此网页的底部查看新评论

由于

/////////////////////////////////////////////// //////// 这是我想与大家分享的最终工作代码 ////////////////////////////////////////////////// /////////////////

#include <omp.h>
#include "Vaes_cipher_top.h"
#include "verilated.h"
#include "verilated_vcd_c.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>



  //#pragma omp threadprivate(top)

vluint64_t main_time = 0;       // Current simulation time
 // This is a 64-bit integer to reduce wrap over issues and
 // allow modulus.  You can also use a double, if you wish.

  double sc_time_stamp ()
{       // Called by $time in Verilog
       return main_time;           // converts to double, to match
                                              // what SystemC does
 }



int main(int argc, char **argv, char **env) 
{
      Verilated::commandArgs(argc, argv);
      srand(time(NULL));


          unsigned int set_done = 0;
          unsigned int i = 0;
          unsigned int ld_set = 0;

    #ifdef OMP
      #pragma omp parallel default(none) firstprivate(i,set_done,ld_set,main_time)
      {
          // unsigned int set_done = 0;
          // unsigned int i = 0;
          // unsigned int ld_set = 0; 
           Vaes_cipher_top* top = new Vaes_cipher_top;  // this is the aes object that will do the enc
           top->rst = 1;           // assert reset
    #endif

        while (i < 65000)
       // #pragma omp parallel for ordered schedule(static) 
       // for(i=0; (i<65000);i++)   
        {

              if (main_time > 10)
              {
                  top->rst = 0;   // Deassert reset
              }
              if ((main_time % 10) == 1)
              {
                  top->clk = 1;       // Toggle clock (posedge)
              }
              if ((main_time % 10) == 6)
              {

                  top->clk = 0;
                  //setting DUT values

              if(ld_set!=1 && main_time > 10)
               {
                  top -> ld = 1;

                  //unsigned int rand_state = time(NULL) + 1337*omp_get_thread_num();
                  //unsigned int rnd[4];      
                  //rnd[0] = rand_r(&rand_state);
                  //rnd[1] = rand_r(&rand_state);
                  //rnd[2] = rand_r(&rand_state);
                  //rnd[3] = rand_r(&rand_state);
                  top -> key     =   {rand(),rand(),rand(),rand()}; // {0x00000000,0x000000000,0x00000000,0x00000000};
                  top -> text_in =   {rand(),rand(),rand(),rand()}; //{0x00000000,0x00000000,0x00000000,0x00000000};  
                  //top -> key     =   {0x00000000,0x00000000,0x00000000,0x00000000};
                  //top -> text_in =   {0x00000000,0x00000000,0x00000000,0x00000000};
                  ld_set++;
                }
                else if(ld_set == 1 && main_time > 10)
                {
                top -> ld = 0;
                set_done = 0;
                }   

                } //(main_time % 10) == 6)

                top->eval();            // Evaluate model

                if(top->done == 1 && set_done == 0)
                {
                #ifdef OMP
                   printf("Time=%2d, key=%2x%2x%2x%2x,text_in=%2x%2x%2x%2x,text_out=%2x%2x%2x%2x on %2d of %2d\n",   \
                           main_time,top->key[3],top->key[2],top->key[1],top->key[0],                               \
                           top->text_in[3],top->text_in[2],top->text_in[1],top->text_in[0],                 \
                           top->text_out[3],top->text_out[2],top->text_out[1],top->text_out[0],top->done, \
                           omp_get_thread_num(),omp_get_num_threads()
                         );
                #else
                   printf("Time=%2d, key=%2x%2x%2x%2x,text_in=%2x%2x%2x%2x,text_out=%2x%2x%2x%2x\n" ,   \
                           main_time,top->key[3],top->key[2],top->key[1],top->key[0],                               \
                           top->text_in[3],top->text_in[2],top->text_in[1],top->text_in[0],                 \
                           top->text_out[3],top->text_out[2],top->text_out[1],top->text_out[0],top->done
                         );
                #endif

                  ld_set = 0; //reset the value 
                    i++;
                  // printf("i=%2d\n",i);
                   set_done  = 1;
                } //if(top->done)

                //#pragma omp barrier   
                main_time++;

          } //end of while


        top->final();               // Done simulating
        delete top;
      } //pragma omp

        printf("\n Test Done\n");


    return 0;
} //end of main

1 个答案:

答案 0 :(得分:1)

你几乎做对了,但Vaes_cipher_top* top;应该在if声明之前移动,例如紧跟在while循环的左大括号之后。同样在这种情况下,top在并行区域外不可见。我建议您按如下方式重构代码:

int main(int argc, char **argv, char **env)
{
   Verilated::commandArgs(argc, argv);

   #pragma omp parallel num_threads(2)
   {
      unsigned int i = 0;
      unsigned int set_done;
      unsigned int ld_set = 0;
      //top->rst = 1;           // assert reset
      unsigned int iter_count = 1;
      Vaes_cipher_top* top = new Vaes_cipher_top;  // this is the aes object that will do the enc

      while (i < 2)
      {
         if (iter_count)
         {
            top = new Vaes_cipher_top;
            iter_count = 0; 
         }
         if (main_time == 0)
            top-> rst = 1;  //assert reset
         if (main_time > 10)
         {
            top->rst = 0;   // Deassert reset
         }
         if ((main_time % 10) == 1)
         {
            top->clk = 1;       // Toggle clock (posedge)
         }
         if ((main_time % 10) == 6)
         {
            top->clk = 0;
            //setting DUT values

            if (ld_set!=1 && main_time > 10)
            {
               top->ld = 1;
               top->key     = {0x00000000,0x00000000,0x00000000,0x00000000};
               top->text_in = {0x00000000,0x00000000,0x00000000,0x00000000};
               ld_set++;
            }
            else if (ld_set == 1 && main_time > 10)
            {
               top->ld = 0;
               set_done = 0;
            }
         } //(main_time % 10) == 6)

         top->eval();            // Evaluate model

         if (top->done && !set_done)
         {
            print(top->key);
            print(top->text_in);
            print(top->text_out);
            ld_set = 0; //reset  
            i++;
            set_done  = 1;
            iter_count = 1; 
         } //if(top->done)

         main_time++;            // Time passes...
      } //end of while 

      top->final();               // Done simulating

      delete top;
   }

   printf("\nTest Done\n");

   return 0;
} //end of main

虽然这与OpenMP无关,但上面的代码会泄漏内存。每次top非零时,都会重新分配iter_count,这在if (top->done && !set_done)条件为真且i仍等于0时发生。可能你应该考虑如何解决这个问题。