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



我正在尝试并行化一个用C/C++翻译的程序。该程序最初使用Verilog硬件描述语言。该程序已由翻译器程序翻译成C/C++。事实上,它是电路级的C/C++程序不应该有什么不同。我基本上是在尝试遵循中的方法

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

但是

当我尝试使用openmp进行并行化时,我遇到了分段故障。这是代码。当我通过写入#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 Donen");
        top->final();               // Done simulating
 delete top;
 return 0;
} //end of main

试图按照赫里斯托的建议前进。没有更多的分段错误,但由于比赛条件导致结果不正确。

 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 Donen");
    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 Donen");
    top->final();               // Done simulating
     delete top;
return 0;
} //end of main

////////////////////////////////////////////////////////////////////////////////////////////这是输出。所有的错误都是一样的。我放了一些

/sim_main.cpp:76:错误:未在此作用域中声明"top"(在top->rst=1的行上)../sim_main.cpp:80:错误:未在此作用域中声明"top"(在top->rst=0的行上)../sim_main.cpp:84:错误:未在此作用域中声明"top"(在top->clk=1的行上)../sim_main.cpp:89:错误:未在此作用域中声明"top"(在top->clk=0的行上)

如果移除Vaes_cipher_top declaration周围的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个核心
of 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 %2dn",   
                           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%2xn" ,   
                           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=%2dn",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 Donen");

    return 0;
} //end of main

您几乎做对了,但Vaes_cipher_top* top;应该移动到if语句之前,例如,立即移动到while循环的左大括号之后。同样在这种情况下,CCD_ 4在平行区域之外将不可见。我建议您按照以下方式重组代码:

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 Donen");
   return 0;
} //end of main

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

最新更新