英文:
Vitis HLS 2022.2 ERROR: [HLS 200-1715] Encountered problem during source synthesis
问题
我是一名Vitis HLS初学者,正在尝试通过构建一个基于提供MD5哈希字符串、字符集和最大长度的暴力破解器来进行练习,理想情况下在PYNQ-Z2上运行它。
到目前为止,我已经成功编写了以下代码,但在Vitis HLS上进行综合时遇到了上述错误。
#include <iostream>
#include <vector>
char* pad_data(const char *data, size_t len, size_t& padded_size);
void md5(const unsigned int *in, unsigned int *out, const size_t size);
void generateCombinations(char* charset, int charset_size);
// 省略部分代码...
int main() {
char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // 你的字符集
int charset_size = strlen(charset);
generateCombinations(charset, charset_size);
return 0;
}
我已经将主函数的部分代码添加到了你的C++代码中,以展示如何调用generateCombinations
函数。你可以将你的字符集和字符集大小传递给generateCombinations
函数以进行测试。
希望这有助于你的工作,如果有任何其他问题或需要进一步的指导,请随时提出。
英文:
I'm a Vitis HLS beginner and trying to practice by building a bruteforcer on an idea of providing MD5 hash string, charset and max length and ideally run it on a PYNQ-Z2.
I've managed to come up with this code up until now and get the above error when synthisizing on Vitis HLS.
#include <iostream>
#include <vector>
char* pad_data(const char *data, size_t len, size_t& padded_size);
void md5(const unsigned int *in, unsigned int *out, const size_t size);
void generateCombinations(char* charset, int charset_size);
//void print_md5(unsigned char* md5);
void generateCombinations(char* charset, int charset_size)
{
#pragma HLS INTERFACE m_axi port=charset
#pragma HLS INTERFACE m_axi port=charset_size
int length = 3;
char current[length+1];
for (size_t i = 0; i < length; i++)
{
current[i] = charset[0];
}
while (true)
{
//std::cout<<current<<std::endl;
char c[length+1];
for (size_t i = 0; i < length; i++)
{
c[i] = current[i];
}
unsigned char out[16];
size_t data_size;
char *pdata = pad_data(c, length, data_size);
md5((unsigned int*)pdata, (unsigned int*)out, data_size);
//print_md5(out);
// check if out is equal to requested MD5 hash
// if yes break and return to AXI port
// Generate next combination
bool carry = true;
for (int i = length - 1; i >= 0; --i) {
if (carry) {
char* ptr;
for (int j = 0; j < charset_size; j++) {
if (charset[j] == current[i]) {
ptr = charset + j;
break;
}
}
int idx = (ptr-charset)+1;
if (idx >= charset_size) {
idx = 0;
carry = true;
}
else {
carry = false;
}
current[i] = charset[idx];
}
}
if (carry) {
break;
}
}
}
char* pad_data(const char *data, size_t len, size_t& padded_size)
{
// Do padding in software for simplicity
size_t mod = (len+1)%64;
size_t pad_size = (64+56-mod)%64;
padded_size = len+1+pad_size+8;
char padded[padded_size];
for (size_t i = 0; i < len; i++)
{
padded[i] = data[i];
}
padded[len] = (char)0x80;
for (size_t i = len+1; i < len+1+pad_size; i++)
{
padded[i] = 0x0;
}
// Convert bytes to bits and append length
len <<= 3;
for(char* p = padded+(padded_size-8); p < padded+padded_size; ++p){
*p = len & 0xff;
len >>= 8;
}
return padded;
}
const unsigned int K[] = {
0XD76AA478,
0XE8C7B756,
0X242070DB,
0XC1BDCEEE,
0XF57C0FAF,
0X4787C62A,
0XA8304613,
0XFD469501,
0X698098D8,
0X8B44F7AF,
0XFFFF5BB1,
0X895CD7BE,
0X6B901122,
0XFD987193,
0XA679438E,
0X49B40821,
0XF61E2562,
0XC040B340,
0X265E5A51,
0XE9B6C7AA,
0XD62F105D,
0X02441453,
0XD8A1E681,
0XE7D3FBC8,
0X21E1CDE6,
0XC33707D6,
0XF4D50D87,
0X455A14ED,
0XA9E3E905,
0XFCEFA3F8,
0X676F02D9,
0X8D2A4C8A,
0XFFFA3942,
0X8771F681,
0X6D9D6122,
0XFDE5380C,
0XA4BEEA44,
0X4BDECFA9,
0XF6BB4B60,
0XBEBFBC70,
0X289B7EC6,
0XEAA127FA,
0XD4EF3085,
0X04881D05,
0XD9D4D039,
0XE6DB99E5,
0X1FA27CF8,
0XC4AC5665,
0XF4292244,
0X432AFF97,
0XAB9423A7,
0XFC93A039,
0X655B59C3,
0X8F0CCC92,
0XFFEFF47D,
0X85845DD1,
0X6FA87E4F,
0XFE2CE6E0,
0XA3014314,
0X4E0811A1,
0XF7537E82,
0XBD3AF235,
0X2AD7D2BB,
0XEB86D391
};
const unsigned char S[][16] = {
{7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22},
{5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20},
{4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23},
{6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21}
};
void md5_round1(const unsigned int *M, const unsigned int *in, unsigned int *out)
{
unsigned int A = in[0];
unsigned int B = in[1];
unsigned int C = in[2];
unsigned int D = in[3];
for(int i=0; i<16; ++i){
unsigned int tmp0 = (B&C)|(~B&D);
unsigned int tmp1 = A + tmp0;
unsigned int tmp2 = M[i] + K[i] + tmp1;
unsigned int tmp3 = (tmp2 << S[0][i]) | (tmp2 >> (32-S[0][i]));
A = D;
D = C;
C = B;
B = tmp3 + B;
}
out[0] = A;
out[1] = B;
out[2] = C;
out[3] = D;
}
void md5_round2(const unsigned int *M, const unsigned int *in, unsigned int *out)
{
unsigned int A = in[0];
unsigned int B = in[1];
unsigned int C = in[2];
unsigned int D = in[3];
for(int i=0; i<16; ++i){
unsigned int tmp0 = (B&D)|(C&~D);
unsigned int tmp1 = A + tmp0;
// unsigned int tmp2 = M[16+i] + K[16+i] + tmp1;
unsigned int tmp2 = M[(((i+16) * 5) + 1) % 16] + K[16+i] + A + tmp0;
unsigned int tmp3 = (tmp2 << S[1][i]) | (tmp2 >> (32-S[1][i]));
A = D;
D = C;
C = B;
B = tmp3 + B;
}
out[0] = A;
out[1] = B;
out[2] = C;
out[3] = D;
}
void md5_round3(const unsigned int *M, const unsigned int *in, unsigned int *out)
{
unsigned int A = in[0];
unsigned int B = in[1];
unsigned int C = in[2];
unsigned int D = in[3];
for(int i=0; i<16; ++i){
unsigned int tmp0 = B^C^D;
unsigned int tmp1 = A + tmp0;
unsigned int tmp2 = M[(((i+32) * 3) + 5) % 16] + K[32+i] + tmp1;
unsigned int tmp3 = (tmp2 << S[2][i]) | (tmp2 >> (32-S[2][i]));
A = D;
D = C;
C = B;
B = tmp3 + B;
}
out[0] = A;
out[1] = B;
out[2] = C;
out[3] = D;
}
void md5_round4(const unsigned int *M, const unsigned int *in, unsigned int *out)
{
unsigned int A = in[0];
unsigned int B = in[1];
unsigned int C = in[2];
unsigned int D = in[3];
for(int i=0; i<16; ++i){
unsigned int tmp0 = C^(B|~D);
unsigned int tmp1 = A + tmp0;
unsigned int tmp2 = M[((i+48) * 7) % 16] + K[48+i] + tmp1;
unsigned int tmp3 = (tmp2 << S[3][i]) | (tmp2 >> (32-S[3][i]));
A = D;
D = C;
C = B;
B = tmp3 + B;
}
out[0] = A;
out[1] = B;
out[2] = C;
out[3] = D;
}
void md5(const unsigned int *in, unsigned int *out, const size_t size)
{
const unsigned int *M = in;
unsigned int v0[] = {0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476};
unsigned int v1[4];
unsigned int v2[4];
unsigned int v3[4];
unsigned int v4[4];
for(size_t i=0; i<size; i+=64)
{
md5_round1(M, v0, v1);
md5_round2(M, v1, v2);
md5_round3(M, v2, v3);
md5_round4(M, v3, v4);
M += 16;
v0[0] += v4[0];
v0[1] += v4[1];
v0[2] += v4[2];
v0[3] += v4[3];
}
out[0] = v0[0];
out[1] = v0[1];
out[2] = v0[2];
out[3] = v0[3];
}
The C++ code works and I was able to compile and run it on x86 machine.
Was also able to solve non-synthisizable issues along the way.
I would highly appreciate any help and guidance that would help me understand what I'm missing or doing wrong.
Thanks so much!
答案1
得分: 1
Here's the translated content:
虽然我无法直接确定问题,但我可以提供一些关于 HLS 的一般建议,这些建议可能有所帮助:
- 你包括了
<vector>
,但实际上没有使用它。特别是对于 HLS,最好严格遵循 iwyu 习惯。并非 C++ 标准的每个部分都可合成,包括额外的代码可能会引发问题。 - 使用 Vivado HLS 中集成的 C 模拟(或者使用自己的编译器),并启用额外的警告,然后仔细检查它们。
pad_data()
返回对局部变量的引用! - 局部变量必须具有固定的大小。你声明了 C 数组,其大小在编译时可能是未知的。HLS 将其转换为硬件,无法在运行时在 FPGA 上分配额外的资源。根据大小和你的指令,这些数组可能会以 LUTs、BRAMs 或 FFs 实现。如果需要在本地存储数据,那么请使用一个上限来声明数组,并手动跟踪大小。
- 包括日志文件。你也可以在 Xilinx 论坛 中找到有用的信息。
英文:
While I can't pinpoint the issue directly I can give some general advice for HLS that may help:
- You include
<vector>
but don't actually use it. Especially for HLS it is best to strictly follow the iwyu idiom. Not every part of the C++ standard is synthesizeable and including additional code may cause issues. - Use the C-Simulation integrated into Vivado HLS (or you use your own compiler) and enable additional warnings and check them thoroughly.
pad_data()
returns a reference to a local variable! - Local variables must have a fixed size. You declare c-arrays which might have unknown size at compile time. HLS translates this to hardware and additional ressources cannot be allocated on the FPGA during runtime. Depending on the size and your directives these arrays may be implemented with LUTs or BRAMs or FFs. If you need to store data locally then use an upper limit to declare your array and keep track of the size manually.
- Include log files. You may also find helpful information in the Xilinx Forums
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论