mirror of
https://github.com/rdolbeau/VexRiscvBPluginGenerator.git
synced 2025-04-16 09:44:41 -04:00
prototype version with 2 cycles instructions
This commit is contained in:
parent
413a570ee9
commit
c56ad23e49
9 changed files with 191 additions and 27 deletions
2
Makefile
2
Makefile
|
@ -60,7 +60,7 @@ PDataProcess.scala: gen_plugin data_Zpn.txt
|
|||
./gen_plugin -n PDataProcess -i data_Zpn.txt -I Zpn >| $@
|
||||
|
||||
PSlowDataProcess.scala: gen_plugin data_Zpn.txt
|
||||
./gen_plugin -n PSlowDataProcess -i data_Zpn.txt -I Zpnslow >| $@
|
||||
./gen_plugin -n PSlowDataProcess -i data_Zpn_2cycles.txt -I Zpn >| $@
|
||||
|
||||
P64DataProcess.scala: gen_plugin data_Zp64.txt
|
||||
./gen_plugin -w -n P64DataProcess -i data_Zp64.txt -I '*' >| $@
|
||||
|
|
46
data_Zpn_2cycles.txt
Normal file
46
data_Zpn_2cycles.txt
Normal file
|
@ -0,0 +1,46 @@
|
|||
|
||||
I SMAQA SMAQA 1100100----------000----01110111 pdpiumul8 Zpn
|
||||
I UMAQA UMAQA 1100110----------000----01110111 pdpismul8 Zpn
|
||||
|
||||
|
||||
S SMAQA "fun_smaqa1(input(SRC1), input(SRC2), input(SRC3))"
|
||||
S UMAQA "fun_umaqa1(input(SRC1), input(SRC2), input(SRC3))"
|
||||
T SMAQA 96 "fun_smaqa2"
|
||||
T UMAQA 96 "fun_umaqa2"
|
||||
|
||||
P """
|
||||
def fun_smaqa1(rs1: Bits, rs2: Bits, rs3: Bits) : Bits = {
|
||||
// 18 bits needed so that intermediate sums don't overflow
|
||||
val h0 = (rs1( 7 downto 0).asSInt * rs2( 7 downto 0).asSInt)
|
||||
val h1 = (rs1(15 downto 8).asSInt * rs2(15 downto 8).asSInt)
|
||||
val h2 = (rs1(23 downto 16).asSInt * rs2(23 downto 16).asSInt)
|
||||
val h3 = (rs1(31 downto 24).asSInt * rs2(31 downto 24).asSInt)
|
||||
rs3 ## h3 ## h2 ## h1 ## h0 // return value 96 bits
|
||||
}
|
||||
def fun_smaqa2(input:Bits ) : Bits = {
|
||||
val r = input(95 downto 64).asSInt + (
|
||||
input(63 downto 48).asSInt.resize(18) +
|
||||
input(47 downto 32).asSInt.resize(18) +
|
||||
input(31 downto 16).asSInt.resize(18) +
|
||||
input(15 downto 0).asSInt.resize(18))
|
||||
|
||||
r.asBits.resize(32) // return value
|
||||
}
|
||||
def fun_umaqa1(rs1: Bits, rs2: Bits, rs3: Bits) : Bits = {
|
||||
// 18 bits needed so that intermediate sums don't overflow
|
||||
val h0 = (rs1( 7 downto 0).asUInt * rs2( 7 downto 0).asUInt)
|
||||
val h1 = (rs1(15 downto 8).asUInt * rs2(15 downto 8).asUInt)
|
||||
val h2 = (rs1(23 downto 16).asUInt * rs2(23 downto 16).asUInt)
|
||||
val h3 = (rs1(31 downto 24).asUInt * rs2(31 downto 24).asUInt)
|
||||
rs3 ## h3 ## h2 ## h1 ## h0 // return value 96 bits
|
||||
}
|
||||
def fun_umaqa2(input:Bits ) : Bits = {
|
||||
val r = input(95 downto 64).asUInt + (
|
||||
input(63 downto 48).asUInt.resize(18) +
|
||||
input(47 downto 32).asUInt.resize(18) +
|
||||
input(31 downto 16).asUInt.resize(18) +
|
||||
input(15 downto 0).asUInt.resize(18))
|
||||
|
||||
r.asBits.resize(32) // return value
|
||||
}
|
||||
"""
|
|
@ -28,6 +28,8 @@ 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;
|
||||
|
||||
|
@ -77,7 +79,15 @@ void add_inst5(const char* name, const char* opname, const char* key, const char
|
|||
instructions.insert(i);
|
||||
}
|
||||
void add_sem(const char* name, const char* sem) {
|
||||
semantics[std::string(name)] = std::string(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));
|
||||
|
@ -155,7 +165,18 @@ int main(int argc, char **argv) {
|
|||
//printf("adding %s\n", inst->name.c_str());
|
||||
}
|
||||
|
||||
unparse(std::cout, pluginName, filtered_instructions, semantics, prologues, extras, wide == 1);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ extern "C" {
|
|||
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);
|
||||
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);
|
||||
void add_sem(const char* name, const char* sem);
|
||||
void add_memsem(const char* name, const int em_width, const char* memsem);
|
||||
void add_prol(const char *prol);
|
||||
void add_extra(const char *extra);
|
||||
#ifdef __cplusplus
|
||||
|
|
31
inst_lex.l
31
inst_lex.l
|
@ -5,35 +5,44 @@
|
|||
* See the LICENSE file at the top level of this software distribution for details.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "inst_par.h"
|
||||
%}
|
||||
|
||||
CHAR [[:alnum:] ,'&./()-]
|
||||
FCHARNAME [[:alpha:]]
|
||||
CHARNAME [[:alnum:]_+-]
|
||||
SPACE [ \t]
|
||||
|
||||
%%
|
||||
|
||||
^"I" { return INST; }
|
||||
^"I" { return INST; }
|
||||
|
||||
^"S" { return SEM; }
|
||||
^"S" { return SEM; }
|
||||
|
||||
^"P" { return PROL; }
|
||||
^"T" { return MEMSEM; }
|
||||
|
||||
^"E" { return EXTRA; }
|
||||
^"P" { return PROL; }
|
||||
|
||||
"//".* { }
|
||||
^"E" { return EXTRA; }
|
||||
|
||||
{CHARNAME}{CHARNAME}{CHARNAME}* { yylval.string = strdup(yytext); return NAME; }
|
||||
"//".* { }
|
||||
|
||||
"\"\"\""[^ù]*"\"\"\"" { yylval.string = strndup(yytext+3, strlen(yytext)-6); return STRING; }
|
||||
{FCHARNAME}{CHARNAME}{CHARNAME}* { yylval.string = strdup(yytext); return NAME; }
|
||||
|
||||
"'''"[^ù]*"'''" { yylval.string = strndup(yytext+3, strlen(yytext)-6); return STRING; }
|
||||
{CHARNAME}{32} { yylval.string = strdup(yytext); return NAME; }
|
||||
|
||||
"\"".*"\"" { yylval.string = strndup(yytext+1, strlen(yytext)-2); return STRING; }
|
||||
|
||||
\n { return yytext[0]; }
|
||||
"\"\"\""[^ù]*"\"\"\"" { yylval.string = strndup(yytext+3, strlen(yytext)-6); return STRING; }
|
||||
|
||||
{SPACE}+ { }
|
||||
"'''"[^ù]*"'''" { yylval.string = strndup(yytext+3, strlen(yytext)-6); return STRING; }
|
||||
|
||||
"\"".*"\"" { yylval.string = strndup(yytext+1, strlen(yytext)-2); return STRING; }
|
||||
|
||||
[0-9][0-9]* { yylval.num = atoi(yytext); return NUM; }
|
||||
|
||||
\n { return yytext[0]; }
|
||||
|
||||
{SPACE}+ { }
|
||||
|
||||
%%
|
||||
|
|
13
inst_par.h
13
inst_par.h
|
@ -47,10 +47,12 @@ extern int yydebug;
|
|||
{
|
||||
NAME = 258,
|
||||
STRING = 259,
|
||||
INST = 260,
|
||||
SEM = 261,
|
||||
PROL = 262,
|
||||
EXTRA = 263
|
||||
NUM = 260,
|
||||
INST = 261,
|
||||
SEM = 262,
|
||||
MEMSEM = 263,
|
||||
PROL = 264,
|
||||
EXTRA = 265
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -61,9 +63,10 @@ union YYSTYPE
|
|||
{
|
||||
#line 14 "inst_par.y" /* yacc.c:1909 */
|
||||
|
||||
int num;
|
||||
char* string;
|
||||
|
||||
#line 67 "inst_par.h" /* yacc.c:1909 */
|
||||
#line 70 "inst_par.h" /* yacc.c:1909 */
|
||||
};
|
||||
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
|
|
|
@ -12,14 +12,17 @@
|
|||
|
||||
%union
|
||||
{
|
||||
int num;
|
||||
char* string;
|
||||
}
|
||||
|
||||
%token <string> NAME
|
||||
%token <string> STRING
|
||||
%token <num> NUM
|
||||
|
||||
%token INST
|
||||
%token SEM
|
||||
%token MEMSEM
|
||||
%token PROL
|
||||
%token EXTRA
|
||||
|
||||
|
@ -36,6 +39,7 @@ INST NAME NAME NAME NAME { /* printf("0 - %s\n", $2); */
|
|||
| INST NAME NAME NAME NAME NAME NAME NAME NAME { /* printf("4 - %s\n", $2); */ add_inst4($2, $3, $4, $5, $6, $7, $8, $9); }
|
||||
| INST NAME NAME NAME NAME NAME NAME NAME NAME NAME { /* printf("5 - %s\n", $2); */ add_inst5($2, $3, $4, $5, $6, $7, $8, $9, $10); }
|
||||
| SEM NAME STRING { add_sem($2, $3); }
|
||||
| MEMSEM NAME NUM STRING { add_memsem($2, $3, $4); }
|
||||
| PROL STRING { add_prol($2); }
|
||||
| EXTRA STRING { add_extra($2); }
|
||||
| '\n'
|
||||
|
|
94
unparse.cpp
94
unparse.cpp
|
@ -8,6 +8,7 @@
|
|||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "inst.hpp"
|
||||
#include "group.hpp"
|
||||
|
@ -39,6 +40,8 @@ void unparse(std::ostream& output,
|
|||
const std::string prefix,
|
||||
const 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,
|
||||
bool wide) {
|
||||
|
@ -48,6 +51,8 @@ void unparse(std::ostream& output,
|
|||
const std::string ctrlEnumString = prefix + "CtrlEnum";
|
||||
const std::string outputString = prefix + "_FINAL_OUTPUT";
|
||||
const std::string isString = "IS_" + prefix;
|
||||
const bool two_cycles = em_widths.size() > 0;
|
||||
const std::string bypassableExecuteString = two_cycles ? "False" : "Bool(earlyInjection)";
|
||||
|
||||
output << "// WARNING: this is auto-generated code!" << std::endl;
|
||||
output << "// See https://github.com/rdolbeau/VexRiscvBPluginGenerator/" << std::endl;
|
||||
|
@ -104,10 +109,17 @@ void unparse(std::ostream& output,
|
|||
output << "} // object Plugin" << std::endl;
|
||||
|
||||
// Plugin class
|
||||
output << "class " << prefix << "Plugin(earlyInjection : Boolean = true) extends Plugin[VexRiscv] {" << std::endl;
|
||||
output << "class " << prefix << "Plugin"; if (!two_cycles) output << "(earlyInjection : Boolean = true)"; output << " extends Plugin[VexRiscv] {" << std::endl;
|
||||
output << '\t' << "import " << prefix << "Plugin._" << std::endl;
|
||||
output << '\t' << "object " << isString << " extends Stageable(Bool)" << std::endl;
|
||||
output << '\t' << "object " << outputString << " extends Stageable(Bits(" << (wide ? 64 : 32) << " bits))" << std::endl;
|
||||
|
||||
if (two_cycles) {
|
||||
for (auto const& pair : em_widths) {
|
||||
std::string regName = prefix + "_INTERMEDIATE_" + pair.first + "" + std::to_string(pair.second);
|
||||
output << '\t' << "object " << regName << " extends Stageable(Bits(" << pair.second << " bits))" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
output << '\t' << "override def setup(pipeline: VexRiscv): Unit = {" << std::endl;
|
||||
output << '\t' << '\t' << "import pipeline.config._" << std::endl;
|
||||
|
@ -118,7 +130,7 @@ void unparse(std::ostream& output,
|
|||
output << '\t' << '\t' << "\tSRC2_CTRL -> Src2CtrlEnum.IMI," << std::endl;
|
||||
output << '\t' << '\t' << "\tREGFILE_WRITE_VALID -> True," << std::endl;
|
||||
if (wide) output << '\t' << '\t' << "\tREGFILE_WRITE_VALID_ODD -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> Bool(earlyInjection)," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> " << bypassableExecuteString << "," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_MEMORY_STAGE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tRS1_USE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\t" << isString << " -> True" << std::endl;
|
||||
|
@ -129,7 +141,7 @@ void unparse(std::ostream& output,
|
|||
output << '\t' << '\t' << "\tSRC2_CTRL -> Src2CtrlEnum.RS," << std::endl;
|
||||
output << '\t' << '\t' << "\tREGFILE_WRITE_VALID -> True," << std::endl;
|
||||
if (wide) output << '\t' << '\t' << "\tREGFILE_WRITE_VALID_ODD -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> Bool(earlyInjection)," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> " << bypassableExecuteString << "," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_MEMORY_STAGE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tRS1_USE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tRS2_USE -> True," << std::endl;
|
||||
|
@ -140,7 +152,7 @@ void unparse(std::ostream& output,
|
|||
output << '\t' << '\t' << "\tSRC1_CTRL -> Src1CtrlEnum.RS," << std::endl;
|
||||
output << '\t' << '\t' << "\tREGFILE_WRITE_VALID -> True," << std::endl;
|
||||
if (wide) output << '\t' << '\t' << "\tREGFILE_WRITE_VALID_ODD -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> Bool(earlyInjection)," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> " << bypassableExecuteString << "," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_MEMORY_STAGE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tRS1_USE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\t" << isString << " -> True" << std::endl;
|
||||
|
@ -152,7 +164,7 @@ void unparse(std::ostream& output,
|
|||
output << '\t' << '\t' << "\tSRC3_CTRL -> Src3CtrlEnum.RS," << std::endl;
|
||||
output << '\t' << '\t' << "\tREGFILE_WRITE_VALID -> True," << std::endl;
|
||||
if (wide) output << '\t' << '\t' << "\tREGFILE_WRITE_VALID_ODD -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> Bool(earlyInjection)," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> " << bypassableExecuteString << "," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_MEMORY_STAGE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tRS1_USE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tRS2_USE -> True," << std::endl;
|
||||
|
@ -166,7 +178,7 @@ void unparse(std::ostream& output,
|
|||
output << '\t' << '\t' << "\tSRC3_CTRL -> Src3CtrlEnum.RS," << std::endl;
|
||||
output << '\t' << '\t' << "\tREGFILE_WRITE_VALID -> True," << std::endl;
|
||||
if (wide) output << '\t' << '\t' << "\tREGFILE_WRITE_VALID_ODD -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> Bool(earlyInjection)," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_EXECUTE_STAGE -> " << bypassableExecuteString << "," << std::endl;
|
||||
output << '\t' << '\t' << "\tBYPASSABLE_MEMORY_STAGE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tRS1_USE -> True," << std::endl;
|
||||
output << '\t' << '\t' << "\tRS3_USE -> True," << std::endl;
|
||||
|
@ -228,7 +240,8 @@ void unparse(std::ostream& output,
|
|||
output << extra << std::endl;
|
||||
output << "// End Extra" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
if (!two_cycles) {
|
||||
output << '\t' << '\t' << "execute plug new Area{" << std::endl;
|
||||
output << '\t' << '\t' << '\t' << "import execute._" << std::endl;
|
||||
|
||||
|
@ -276,8 +289,73 @@ void unparse(std::ostream& output,
|
|||
output << '\t' << '\t' << '\t' << '\t' << "output(REGFILE_WRITE_DATA) := input(" << outputString << ")" << std::endl;
|
||||
}
|
||||
output << '\t' << '\t' << '\t' << "} // when input is" << std::endl;
|
||||
|
||||
output << '\t' << '\t' << "} // injectionStage plug newArea" << std::endl;
|
||||
} else { // two-cycles
|
||||
output << '\t' << '\t' << "execute plug new Area{" << std::endl;
|
||||
output << '\t' << '\t' << '\t' << "import execute._" << std::endl;
|
||||
for (auto const& pair : em_widths) {
|
||||
std::string regName = prefix + "_INTERMEDIATE_" + pair.first + "" + std::to_string(pair.second);
|
||||
output << '\t' << '\t' << '\t' << "insert(" << regName << ") := " << semantics[pair.first] << ".asBits" << std::endl;
|
||||
}
|
||||
output << '\t' << '\t' << "} // execute plug newArea" << std::endl;
|
||||
output << '\t' << '\t' << "memory plug new Area{" << std::endl;
|
||||
output << '\t' << '\t' << '\t' << "import memory._" << std::endl;
|
||||
// 2nd level MUXes
|
||||
for (const group* g : *groups) {
|
||||
if (g->opnames.size() > 1) {
|
||||
output << '\t' << '\t' << '\t' << "val val_" << g->name << " = input("<< ctrlString << g->name << ").mux(" << std::endl;
|
||||
for (auto it = g->opnames.begin() ; it != g->opnames.end() ; it++) {
|
||||
std::string opname = *it;
|
||||
std::string semantic = semantics[opname];
|
||||
std::string regName = prefix + "_INTERMEDIATE_" + opname + "" + std::to_string(em_widths[opname]);
|
||||
output << '\t' << '\t' << '\t' << '\t' << ctrlString << g->name << "Enum.CTRL_" << opname << " -> " << mem_semantics[opname] << "(input(" << regName << ")).asBits";
|
||||
if (std::next(it, 1) == g->opnames.end())
|
||||
output << std::endl;
|
||||
else
|
||||
output << "," << std::endl;
|
||||
}
|
||||
output << '\t' << '\t' << '\t' << ") // mux " << g->name << std::endl;
|
||||
}
|
||||
}
|
||||
// conditional last level mux
|
||||
output << '\t' << '\t' << '\t' << "when (arbitration.isValid && input(" << isString << ")) {" << std::endl;
|
||||
output << '\t' << '\t' << '\t' << '\t' << "output(REGFILE_WRITE_DATA) := input(" << ctrlString << ").mux(" << std::endl;
|
||||
for (auto it = groups->begin() ; it != groups->end() ; it++) {
|
||||
group* g = *it;
|
||||
if (g->opnames.size() > 1) {
|
||||
output << '\t' << '\t' << '\t' << '\t' <<'\t' << ctrlEnumString << "." << g->ctrlName() << " -> val_" << g->name << ".asBits";
|
||||
} else {
|
||||
std::string opname = *g->opnames.begin();
|
||||
std::string regName = prefix + "_INTERMEDIATE_" + opname + "" + std::to_string(em_widths[opname]);
|
||||
output << '\t' << '\t' << '\t' << '\t' << '\t' << ctrlEnumString << ".CTRL_" << opname << " -> " << mem_semantics[opname] << "(input(" << regName << ")).asBits(31 downto 0)";
|
||||
}
|
||||
if (std::next(it, 1) == groups->end())
|
||||
output << std::endl;
|
||||
else
|
||||
output << "," << std::endl;
|
||||
}
|
||||
output << '\t' << '\t' << '\t' << '\t' << ") // primary mux" << std::endl;
|
||||
if (wide) {
|
||||
output << '\t' << '\t' << '\t' << '\t' << "output(REGFILE_WRITE_DATA_ODD) := input(" << ctrlString << ").mux(" << std::endl;
|
||||
for (auto it = groups->begin() ; it != groups->end() ; it++) {
|
||||
group* g = *it;
|
||||
if (g->opnames.size() > 1) {
|
||||
output << '\t' << '\t' << '\t' << '\t' <<'\t' << ctrlEnumString << "." << g->ctrlName() << " -> val_" << g->name << ".asBits";
|
||||
} else {
|
||||
std::string opname = *g->opnames.begin();
|
||||
std::string regName = prefix + "_INTERMEDIATE_" + opname + "" + std::to_string(em_widths[opname]);
|
||||
output << '\t' << '\t' << '\t' << '\t' << '\t' << ctrlEnumString << ".CTRL_" << opname << " -> " << mem_semantics[opname] << "(input(" << regName << ")).asBits(63 downto 32)";
|
||||
}
|
||||
if (std::next(it, 1) == groups->end())
|
||||
output << std::endl;
|
||||
else
|
||||
output << "," << std::endl;
|
||||
}
|
||||
}
|
||||
output << '\t' << '\t' << '\t' << '\t' << ") // primary mux" << std::endl;
|
||||
output << '\t' << '\t' << '\t' << "} // when input is" << std::endl;
|
||||
output << '\t' << '\t' << "} // memory plug newArea" << std::endl;
|
||||
}
|
||||
output << '\t' << "} // override def build" << std::endl;
|
||||
output << "} // class Plugin" << std::endl;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ void unparse(std::ostream& output,
|
|||
const std::string prefix,
|
||||
const 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,
|
||||
bool wide);
|
||||
|
|
Loading…
Add table
Reference in a new issue