Skip to content

Instantly share code, notes, and snippets.

@Aniruddha-Deb
Last active March 5, 2022 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Aniruddha-Deb/192462b220dba7e9c4316d6fdbfdee74 to your computer and use it in GitHub Desktop.
Save Aniruddha-Deb/192462b220dba7e9c4316d6fdbfdee74 to your computer and use it in GitHub Desktop.
generate VHDL test benches from an assembly file
#include <stdio.h>
#include <stdlib.h>
typedef char byte;
typedef unsigned int word;
char* header =
"-- TESTCASE AUTOGENERATED by gentest\n"
"library ieee;\n"
"use ieee.std_logic_1164.all;\n"
"use ieee.numeric_std.all;\n"
"use work.MyTypes.all;\n"
"\n"
"entity cpu_tb is\n"
"end cpu_tb;\n"
"\n"
"architecture cpu_tb_arc of cpu_tb is\n"
" signal clock: std_logic := '0';\n"
" constant clock_period: time := 2 ns;\n"
" signal memory: mem(127 downto 0) := (\n";
char* footer = "begin\n"
" uut: entity work.cpu generic map (memory) port map (clock);\n"
"\n"
" clock <= not clock after clock_period/2;\n"
"\n"
"end cpu_tb_arc;\n";
byte* get_file_as_bytes(char* fname) {
FILE *fileptr;
char *buffer;
long filelen;
fileptr = fopen(fname, "rb"); // Open the file in binary mode
fseek(fileptr, 0, SEEK_END); // Jump to the end of the file
filelen = ftell(fileptr); // Get the current byte offset in the file
rewind(fileptr); // Jump back to the beginning of the file
buffer = (char *)malloc(filelen * sizeof(char)); // Enough memory for the file
fread(buffer, filelen, 1, fileptr); // Read in the entire file
fclose(fileptr); // Close the file
return buffer;
}
int main(int argc, char** argv) {
// first argument contains assembly file to generate testcase for
// second argument is output vhdl filename
if (argc < 3) {
printf("Incorrect format. Ending.");
return 1;
}
char* fname = argv[1];
// compile the file
char* cmd = (char*)malloc(200);
sprintf(cmd, "/Applications/ARM/bin/arm-none-eabi-as -march=armv4t -mbig-endian %s", fname);
int result = system(cmd);
if (result != 0) {
printf("Could not compile file. Exiting.");
return 1;
}
free(cmd);
// post compilation, open the executable as a byte array
byte* fbytes = get_file_as_bytes("a.out");
// open output file for writing
FILE *outfile;
outfile = fopen(argv[2], "w");
fprintf(outfile, header);
// compiled as an ELF on my machine; commands start from 13th word, in
// big endian order (big endian makes a hexdump easier to read)
for (int i = 13*4,j=0; ; i+=4,j++) {
word cmd = ((word)fbytes[i] << 24) |
((word)fbytes[i+1] << 16) |
((word)fbytes[i+2] << 8) |
((word)fbytes[i+3]);
if (cmd == (((word)0x41)<<24)) { // ELF command signifying end of instructions
break;
}
else {
fprintf(outfile, " %d => X\"%02hhX%02hhX%02hhX%02hhX\",\n", j, fbytes[i], fbytes[i+1], fbytes[i+2], fbytes[i+3]);
}
}
fprintf(outfile, " others => X\"00000000\" );\n");
fprintf(outfile, footer);
free(fbytes);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment