c语言算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include<stdio.h> #include<string> #include<ctype.h>
void encrypt(char *plaintext, int shift) { int length = strlen(plaintext); for(int i = 0; i < length; i++) { char current = plaintext[i]; if(isalpha(current)) { char base = islower(current) ? 'a' : 'A'; plaintext[i] = (current - base + shift) % 26 + base; } else exit(-1); } }
int main() { char plaintext[100]; for(i = 0; i < 100; i++) { plaintext[i] = 'a'; } int shift = 5; encrypt(plaintext, shift); return 0; }
|
上述是c语言代码,但是,在HLS中,只支持最基本的c语言函数,所以像字符串的很多函数比如strlen(), islower()
都不支持。我们需要自己编写。
HLS中算法修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include<stdio.h> #include<string.h> #include<ctype.h>
int calculate_length(char *string) { int len = 0; while (string[len] != '\0') { len++; } return len; }
void encrypt(char *plaintext, int shift) { int length = calculate_length(plaintext); for(int i = 0; i < length; i++) { char current = plaintext[i]; if((current >='a' && current <= 'z') || (current >= 'A' && current <= 'Z')) { char base = (current >='a' && current <= 'z') ? 'a' : 'A'; plaintext[i] = (current - base + shift) % 26 + base; } } }
|
我们进行仿真,上述代码已经修改正确。(并非最终代码)

我们观察仿真出来的verilog代码,看到shift位宽32位如图所示:

然而位移最多26位,所以将宽度限制为5位即可。
所以定义一个头文件,在其中定义一些数据类型。
1 2 3 4 5 6 7 8 9 10
| #ifndef _SHIFT_ENCRYPT_H #define _SHIFT_ENCRYPT_H
#include "ap_int.h"
typedef ap_fixed<5, 5> shift_t;
void encrypt(char *plaintext, int shift); #endif
|
之后我们要修改我们的源文件shift_encrypt.cpp
如下:(并非最终代码)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include<stdio.h> #include<string.h> #include<ctype.h> #include "D:\Vitis_HLS\shift_encrypt\src\shift_encrypt.h" int calculate_length(char *string) { int len = 0; while (string[len] != '\0') { len++; } return len; }
void encrypt(char *plaintext, shift_t shift) { int length = calculate_length(plaintext); for(int i = 0; i < length; i++) { char current = plaintext[i]; if((current >='a' && current <= 'z') || (current >= 'A' && current <= 'Z')) { char base = (current >='a' && current <= 'z') ? 'a' : 'A'; plaintext[i] = (current - base + (int)shift) % 26 + base; } } }
|
重新运行仿真,即可看到shift占位5bits.
注意,此时还有问题,因为我们的输入和输出都是同一个地址处的变量plaintext,不利于区分输入和输出端口,所以我们应该定义输入和输出,分开赋值,便于接口分配。
最终代码
所以修改之后的shift_encrypt
文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include<stdio.h> #include<string.h> #include<ctype.h> #include "D:\Vitis_HLS\shift_encrypt\src\shift_encrypt.h"
void encrypt(char *input, shift_t shift, char *output) { encrypt_label0:for(shift_t i = 0; i < 3; i++) { char current = input[i]; if((current >='a' && current <= 'z') || (current >= 'A' && current <= 'Z')) { char base = (current >='a' && current <= 'z') ? 'a' : 'A'; output[i] = (current - base + (int)shift) % 26 + base; } } }
|
修改的testbench.cpp
文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include<stdio.h> #include<string> #include<ctype.h> #include "D:\Vitis_HLS\shift_encrypt\src\shift_encrypt.h" int main() { char input[4] = "aaa"; char output[4]; shift_t shift = 5; encrypt(input, shift, output); fprintf(stdout, "output result = %s\n", output); return 0; }
|
现在查看仿真报告可以看到端口输入输出端口明确。联合仿真之后可以查看波形,确定我们的testbench很好的适应源文件。

我们尝试新建了一个solution,并且保留之前solution的directives
文件,

然后我们在这个solution中添加pipeline优化看能不能优化latency。

然后对solution2进行综合,并且对比其与solution1综合的报告,对比latency。