VexRiscvBPluginGenerator/gen_plugin.cpp
2021-02-14 03:18:11 -05:00

182 lines
5.5 KiB
C++

/*
* Copyright (c) 2020 Romain Dolbeau <romain.dolbeau@european-processor-initiative.eu>
* MIT License
* See the LICENSE file at the top level of this software distribution for details.
*/
#include <iostream>
#include <set>
#include <map>
#include <vector>
#include "inst.hpp"
#include "unparse.hpp"
#include "gen_plugin.hpp"
#include <cstring>
#include <unistd.h>
// yucc
extern "C" {
#include "inst_par.h"
extern FILE *yyin, *yyout;
extern int yydebug;
}
std::set<const instruction*> instructions;
std::map<std::string, std::string> semantics;
std::map<std::string, int> em_widths;
std::map<std::string, std::string> mem_semantics;
std::vector<std::string> prologues;
std::vector<std::string> extras;
void add_inst0(const char* name, const char* opname, const char* key, const char* group) {
if (strlen(key) != 32) { fprintf(stderr, "For %s / %s: %s isn't 32 characters long\n", name, opname, key); }
instruction* i = new instruction(name, opname, key, group);
instructions.insert(i);
}
void add_inst1(const char* name, const char* opname, const char* key, const char* group, const char* e1) {
if (strlen(key) != 32) { fprintf(stderr, "For %s / %s: %s isn't 32 characters long\n", name, opname, key); }
instruction* i = new instruction(name, opname, key, group);
i->addExt(e1);
instructions.insert(i);
}
void add_inst2(const char* name, const char* opname, const char* key, const char* group, const char* e1, const char* e2) {
if (strlen(key) != 32) { fprintf(stderr, "For %s / %s: %s isn't 32 characters long\n", name, opname, key); }
instruction* i = new instruction(name, opname, key, group);
i->addExt(e1);
i->addExt(e2);
instructions.insert(i);
}
void add_inst3(const char* name, const char* opname, const char* key, const char* group, const char* e1, const char* e2, const char *e3) {
if (strlen(key) != 32) { fprintf(stderr, "For %s / %s: %s isn't 32 characters long\n", name, opname, key); }
instruction* i = new instruction(name, opname, key, group);
i->addExt(e1);
i->addExt(e2);
i->addExt(e3);
instructions.insert(i);
}
void add_inst4(const char* name, const char* opname, const char* key, const char* group, const char* e1, const char* e2, const char *e3, const char *e4) {
if (strlen(key) != 32) { fprintf(stderr, "For %s / %s: %s isn't 32 characters long\n", name, opname, key); }
instruction* i = new instruction(name, opname, key, group);
i->addExt(e1);
i->addExt(e2);
i->addExt(e3);
i->addExt(e4);
instructions.insert(i);
}
void add_inst5(const char* name, const char* opname, const char* key, const char* group, const char* e1, const char* e2, const char *e3, const char *e4, const char *e5) {
if (strlen(key) != 32) { fprintf(stderr, "For %s / %s: %s isn't 32 characters long\n", name, opname, key); }
instruction* i = new instruction(name, opname, key, group);
i->addExt(e1);
i->addExt(e2);
i->addExt(e3);
i->addExt(e4);
i->addExt(e5);
instructions.insert(i);
}
void add_sem(const char* name, const char* sem) {
const std::string key(name);
semantics[key] = std::string(sem);
}
void add_memsem(const char* name, const int em_width, const char* memsem) {
const std::string key(name);
if ((em_width > 0) && (memsem != NULL)) {
em_widths[key] = em_width;
mem_semantics[key] = std::string(memsem);
}
}
void add_prol(const char *prol) {
prologues.push_back(std::string(prol));
}
void add_extra(const char *extra) {
extras.push_back(std::string(extra));
}
int main(int argc, char **argv) {
int c, done = 0, wide = 0;
extern char *optarg;
extern int optind, optopt;
FILE *myfile;
char *pluginName = NULL;
#define MAX_INSTS 1024
char* insts[MAX_INSTS];
int instidx = 0;
while ((c = getopt(argc, argv, "n:i:I:w")) != -1) {
switch(c) {
default:
fprintf(stderr, "usage: %s [-w] -n <plugin_name> -i <input_file> -I <instructions> \n", argv[0]);
break;
case 'i':
myfile = fopen(optarg, "r");
if (!myfile) {
fprintf(stderr, "no file\n");
return -1;
}
yyin = myfile;
do {
yyparse();
} while (!feof(yyin));
fclose(myfile);
done = 1;
break;
case 'n':
pluginName = strndup(optarg, 512);
break;
case 'I':
if (instidx < MAX_INSTS) {
insts[instidx] = strndup(optarg, 512);
instidx ++;
}
break;
case 'w':
wide = 1;
break;
}
}
if (!done || !pluginName || (instidx == 0)) {
std::cerr << "Should have at least a plugin name & a datafile & some instructions enabled" << std::endl;
exit(-1);
}
std::set<const instruction*> filtered_instructions;
for (const instruction* inst : instructions) {
// if (inst->isWord())
// continue;
if (semantics[inst->opname] == "")
continue;
bool addinst = false;
for (int i = 0 ; i < instidx; i++) {
if (inst->match(insts[i]) || (strncmp(insts[i], "*", 1)==0)) {
// printf("%s is in %s\n", inst->name.c_str(), insts[i]);
addinst = true;
} else {
// printf("%s is NOT in %s\n", inst->name.c_str(), insts[i]);
}
}
if (addinst)
filtered_instructions.insert(inst);
//printf("adding %s\n", inst->name.c_str());
}
if ((em_widths.size() != 0) || (mem_semantics.size() !=0)) {
if (em_widths.size() != mem_semantics.size()) {
std::cerr << "Multicycle error: emwidths.size() != mem_semantics.size()" << std::endl;
exit(-1);
}
if (semantics.size() != mem_semantics.size()) {
std::cerr << "Multicycle error: semantics.size() != mem_semantics.size() (all instructions should have the same nuber of cycles in the same plugin)" << std::endl;
exit(-1);
}
}
unparse(std::cout, pluginName, filtered_instructions, semantics, em_widths, mem_semantics, prologues, extras, wide == 1);
return 0;
}