From 0bee5d8ca0bd696445bf752e9c833a71ded52fc9 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Mon, 2 Dec 2019 14:58:52 -0800 Subject: [PATCH 01/20] WIP inline operators --- include/coreir/definitions/coreVerilog.hpp | 228 +++++++++++++++++---- 1 file changed, 190 insertions(+), 38 deletions(-) diff --git a/include/coreir/definitions/coreVerilog.hpp b/include/coreir/definitions/coreVerilog.hpp index fadedea33..6dbc147d3 100644 --- a/include/coreir/definitions/coreVerilog.hpp +++ b/include/coreir/definitions/coreVerilog.hpp @@ -1,55 +1,207 @@ +#include "verilogAST.hpp" +namespace vAST = verilogAST; + +std::vector> + make_args(std::vector args) { + std::vector> arg_ptrs; + for (auto a : args) { + arg_ptrs.push_back(vAST::make_id(a)); + } + return arg_ptrs; +} + +std::unique_ptr make_signed_call(const char *id) { + std::vector> args; + args.push_back(vAST::make_id(std::string(id))); + return std::make_unique("$signed", std::move(args)); +} using namespace CoreIR; using namespace std; void CoreIRLoadVerilog_coreir(Context* c) { - std::map> coreVMap({ + std::map> + coreVMap({ {"unary",{ - {"wire","in"}, - {"not","~in"}, - {"neg","-in"} + {"wire","in", + vAST::make_id("in") + }, + {"not","~in", + vAST::UnaryOp(vAST::make_id("in"), + vAST::UnOp::INVERT) + }, + {"neg","-in", + vAST::UnaryOp(vAST::make_id("in"), + vAST::UnOp::MINUS) + } }}, {"unaryReduce",{ - {"andr","&in"}, - {"orr","|in"}, - {"xorr","^in"} + {"andr","&in", + vAST::UnaryOp(vAST::make_id("in"), + vAST::UnOp::AND) + }, + {"orr","|in", + vAST::UnaryOp(vAST::make_id("in"), + vAST::UnOp::OR) + }, + {"xorr","^in", + vAST::UnaryOp(vAST::make_id("in"), + vAST::UnOp::XOR) + } }}, {"binary",{ - {"and","in0 & in1"}, - {"or","in0 | in1"}, - {"xor","in0 ^ in1"}, - {"shl","in0 << in1"}, - {"lshr","in0 >> in1"}, - {"ashr","$signed(in0) >>> in1"}, - {"add","in0 + in1"}, - {"sub","in0 - in1"}, - {"mul","in0 * in1"}, - {"udiv","in0 / in1"}, - {"sdiv","$signed(in0) / $signed(in1)"} + {"and","in0 & in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::AND, + vAST::make_id("in1")) + }, + {"or","in0 | in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::OR, + vAST::make_id("in1")) + }, + {"xor","in0 ^ in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::XOR, + vAST::make_id("in1")) + }, + {"shl","in0 << in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::LSHIFT, + vAST::make_id("in1")) + }, + {"lshr","in0 >> in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::RSHIFT, + vAST::make_id("in1")) + }, + {"ashr","$signed(in0) >>> in1", + vAST::BinaryOp(make_signed_call("in0"), + vAST::BinOp::ARSHIFT, + vAST::make_id("in1")) + }, + {"add","in0 + in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::ADD, + vAST::make_id("in1")) + }, + {"sub","in0 - in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::SUB, + vAST::make_id("in1")) + }, + {"mul","in0 * in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::MUL, + vAST::make_id("in1")) + }, + {"udiv","in0 / in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::DIV, + vAST::make_id("in1")) + }, + {"sdiv","$signed(in0) / $signed(in1)", + vAST::BinaryOp(make_signed_call("in0"), + vAST::BinOp::DIV, + make_signed_call("in1")) + } }}, {"binaryReduce",{ - {"eq","in0 == in1"}, - {"neq","in0 != in1"}, - {"slt","$signed(in0) < $signed(in1)"}, - {"sgt","$signed(in0) > $signed(in1)"}, - {"sle","$signed(in0) <= $signed(in1)"}, - {"sge","$signed(in0) >= $signed(in1)"}, - {"ult","in0 < in1"}, - {"ugt","in0 > in1"}, - {"ule","in0 <= in1"}, - {"uge","in0 >= in1"} + {"eq","in0 == in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::EQ, + vAST::make_id("in1")) + }, + {"neq","in0 != in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::NEQ, + vAST::make_id("in1")) + }, + {"slt","$signed(in0) < $signed(in1)", + vAST::BinaryOp(make_signed_call("in0"), + vAST::BinOp::LT, + make_signed_call("in1")) + }, + {"sgt","$signed(in0) > $signed(in1)", + vAST::BinaryOp(make_signed_call("in0"), + vAST::BinOp::GT, + make_signed_call("in1")) + }, + {"sle","$signed(in0) <= $signed(in1)", + vAST::BinaryOp(make_signed_call("in0"), + vAST::BinOp::LTE, + make_signed_call("in1")) + }, + {"sge","$signed(in0) >= $signed(in1)", + vAST::BinaryOp(make_signed_call("in0"), + vAST::BinOp::GTE, + make_signed_call("in1")) + }, + {"ult","in0 < in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::LT, + vAST::make_id("in1")) + }, + {"ugt","in0 > in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::GT, + vAST::make_id("in1")) + }, + {"ule","in0 <= in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::LTE, + vAST::make_id("in1")) + }, + {"uge","in0 >= in1", + vAST::BinaryOp(vAST::make_id("in0"), + vAST::BinOp::GTE, + vAST::make_id("in1")) + } }}, {"other",{ - {"mux","sel ? in1 : in0"}, - {"slice","in[hi-1:lo]"}, - {"concat","{in1,in0}"}, - {"zext","{{(width_out-width_in){1'b0}},in}"}, - {"sext","{{(width_out-width_in){in[width_in-1]}},in}"}, - {"strip","in"}, - {"wrap","in"}, - {"const","value"}, - {"tribuf","en ? in : 'hz"}, - {"ibuf","in"}, + {"mux","sel ? in1 : in0", + vAST::TernaryOp( + vAST::make_id("sel"), + vAST::make_id("in1"), + vAST::make_id("in0")) + }, + {"slice","in[hi-1:lo]", + vAST::Slice( + vAST::make_id("in"), + vAST::make_binop( + vAST::make_id("hi"), + vAST::BinOp::SUB, + vAST::make_num("1") + ), + vAST::make_id("lo")) + }, + {"concat","{in1,in0}", + vAST::Concat(make_args({"in1", "in0"})) + }, + {"zext","{{(width_out-width_in){1'b0}},in}", + + }, + {"sext","{{(width_out-width_in){in[width_in-1]}},in}", + + }, + {"strip","in", + vAST::make_id("in") + }, + {"wrap","in", + vAST::make_id("in") + }, + {"const","value", + vAST::make_id("value") + }, + {"tribuf","en ? in : 'hz", + vAST::TernaryOp( + vAST::make_id("en"), + vAST::make_id("in"), + std::make_unique("z", vAST::Radix::HEX)) + }, + {"ibuf","in", + vAST::make_id("in") + }, //{"term",""} //{"reg",""}, //{"mem",""}, From 6a01272aedbb676222263fddbc2bf94b6dbc2dc4 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Thu, 5 Dec 2019 17:32:13 -0800 Subject: [PATCH 02/20] Define operator ASTs --- include/coreir/definitions/coreVerilog.hpp | 348 +++++++++++---------- 1 file changed, 185 insertions(+), 163 deletions(-) diff --git a/include/coreir/definitions/coreVerilog.hpp b/include/coreir/definitions/coreVerilog.hpp index 6dbc147d3..024e3f36b 100644 --- a/include/coreir/definitions/coreVerilog.hpp +++ b/include/coreir/definitions/coreVerilog.hpp @@ -11,6 +11,11 @@ std::vector> return arg_ptrs; } +std::vector> + make_ext_args(std::vector> args) { + return args; +} + std::unique_ptr make_signed_call(const char *id) { std::vector> args; args.push_back(vAST::make_id(std::string(id))); @@ -20,188 +25,205 @@ std::unique_ptr make_signed_call(const char *id) { using namespace CoreIR; using namespace std; void CoreIRLoadVerilog_coreir(Context* c) { - std::map> + std::map()>>>> coreVMap({ {"unary",{ - {"wire","in", - vAST::make_id("in") - }, - {"not","~in", - vAST::UnaryOp(vAST::make_id("in"), - vAST::UnOp::INVERT) - }, - {"neg","-in", - vAST::UnaryOp(vAST::make_id("in"), - vAST::UnOp::MINUS) - } + {"wire",{ + "in", + []() {return vAST::make_id("in");} + }}, + {"not",{ + "~in", + []() {return std::make_unique(vAST::make_id("in"), vAST::UnOp::INVERT);} + }}, + {"neg",{ + "-in", + []() {return std::make_unique(vAST::make_id("in"), vAST::UnOp::MINUS);} + }} }}, {"unaryReduce",{ - {"andr","&in", - vAST::UnaryOp(vAST::make_id("in"), - vAST::UnOp::AND) - }, - {"orr","|in", - vAST::UnaryOp(vAST::make_id("in"), - vAST::UnOp::OR) - }, - {"xorr","^in", - vAST::UnaryOp(vAST::make_id("in"), - vAST::UnOp::XOR) - } + {"andr",{"&in", + []() {return std::make_unique(vAST::make_id("in"), vAST::UnOp::AND);} + }}, + {"orr",{"|in", + []() {return std::make_unique(vAST::make_id("in"), vAST::UnOp::OR);} + }}, + {"xorr",{"^in", + []() {return std::make_unique(vAST::make_id("in"), vAST::UnOp::XOR);} + }} }}, {"binary",{ - {"and","in0 & in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::AND, - vAST::make_id("in1")) - }, - {"or","in0 | in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::OR, - vAST::make_id("in1")) - }, - {"xor","in0 ^ in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::XOR, - vAST::make_id("in1")) - }, - {"shl","in0 << in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::LSHIFT, - vAST::make_id("in1")) - }, - {"lshr","in0 >> in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::RSHIFT, - vAST::make_id("in1")) - }, - {"ashr","$signed(in0) >>> in1", - vAST::BinaryOp(make_signed_call("in0"), - vAST::BinOp::ARSHIFT, - vAST::make_id("in1")) - }, - {"add","in0 + in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::ADD, - vAST::make_id("in1")) - }, - {"sub","in0 - in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::SUB, - vAST::make_id("in1")) - }, - {"mul","in0 * in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::MUL, - vAST::make_id("in1")) - }, - {"udiv","in0 / in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::DIV, - vAST::make_id("in1")) - }, - {"sdiv","$signed(in0) / $signed(in1)", - vAST::BinaryOp(make_signed_call("in0"), - vAST::BinOp::DIV, - make_signed_call("in1")) - } + {"and",{"in0 & in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::AND, vAST::make_id("in1")); + }}}, + {"or",{"in0 | in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::OR, vAST::make_id("in1")); + }}}, + {"xor",{"in0 ^ in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::XOR, vAST::make_id("in1")); + }}}, + {"shl",{"in0 << in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::LSHIFT, vAST::make_id("in1")); + }}}, + {"lshr",{"in0 >> in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::RSHIFT, vAST::make_id("in1")); + }}}, + {"ashr",{"$signed(in0) >>> in1", + []() {return std::make_unique(make_signed_call("in0"), + vAST::BinOp::ARSHIFT, vAST::make_id("in1")); + }}}, + {"add",{"in0 + in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::ADD, vAST::make_id("in1")); + }}}, + {"sub",{"in0 - in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::SUB, vAST::make_id("in1")); + }}}, + {"mul",{"in0 * in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::MUL, vAST::make_id("in1")); + }}}, + {"udiv",{"in0 / in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::DIV, vAST::make_id("in1")); + }}}, + {"sdiv",{"$signed(in0) / $signed(in1)", + []() {return std::make_unique(make_signed_call("in0"), + vAST::BinOp::DIV, make_signed_call("in1")); + }}} }}, {"binaryReduce",{ - {"eq","in0 == in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::EQ, - vAST::make_id("in1")) - }, - {"neq","in0 != in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::NEQ, - vAST::make_id("in1")) - }, - {"slt","$signed(in0) < $signed(in1)", - vAST::BinaryOp(make_signed_call("in0"), - vAST::BinOp::LT, - make_signed_call("in1")) - }, - {"sgt","$signed(in0) > $signed(in1)", - vAST::BinaryOp(make_signed_call("in0"), - vAST::BinOp::GT, - make_signed_call("in1")) - }, - {"sle","$signed(in0) <= $signed(in1)", - vAST::BinaryOp(make_signed_call("in0"), - vAST::BinOp::LTE, - make_signed_call("in1")) - }, - {"sge","$signed(in0) >= $signed(in1)", - vAST::BinaryOp(make_signed_call("in0"), - vAST::BinOp::GTE, - make_signed_call("in1")) - }, - {"ult","in0 < in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::LT, - vAST::make_id("in1")) - }, - {"ugt","in0 > in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::GT, - vAST::make_id("in1")) - }, - {"ule","in0 <= in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::LTE, - vAST::make_id("in1")) - }, - {"uge","in0 >= in1", - vAST::BinaryOp(vAST::make_id("in0"), - vAST::BinOp::GTE, - vAST::make_id("in1")) - } + {"eq",{"in0 == in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::EQ, vAST::make_id("in1")); + }}}, + {"neq",{"in0 != in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::NEQ, vAST::make_id("in1")); + }}}, + {"slt",{"$signed(in0) < $signed(in1)", + []() {return std::make_unique(make_signed_call("in0"), + vAST::BinOp::LT, make_signed_call("in1")); + }}}, + {"sgt",{"$signed(in0) > $signed(in1)", + []() {return std::make_unique(make_signed_call("in0"), + vAST::BinOp::GT, make_signed_call("in1")); + }}}, + {"sle",{"$signed(in0) <= $signed(in1)", + []() {return std::make_unique(make_signed_call("in0"), + vAST::BinOp::LTE, make_signed_call("in1")); + }}}, + {"sge",{"$signed(in0) >= $signed(in1)", + []() {return std::make_unique(make_signed_call("in0"), + vAST::BinOp::GTE, make_signed_call("in1")); + }}}, + {"ult",{"in0 < in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::LT, vAST::make_id("in1")); + }}}, + {"ugt",{"in0 > in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::GT, vAST::make_id("in1")); + }}}, + {"ule",{"in0 <= in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::LTE, vAST::make_id("in1")); + }}}, + {"uge",{"in0 >= in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::GTE, vAST::make_id("in1")); + }}} }}, {"other",{ - {"mux","sel ? in1 : in0", - vAST::TernaryOp( + {"mux",{"sel ? in1 : in0", + [](){ return std::make_unique( vAST::make_id("sel"), vAST::make_id("in1"), - vAST::make_id("in0")) - }, - {"slice","in[hi-1:lo]", - vAST::Slice( + vAST::make_id("in0")); + }}}, + {"slice",{"in[hi-1:lo]", + [](){ return std::make_unique( vAST::make_id("in"), vAST::make_binop( vAST::make_id("hi"), vAST::BinOp::SUB, vAST::make_num("1") ), - vAST::make_id("lo")) - }, - {"concat","{in1,in0}", - vAST::Concat(make_args({"in1", "in0"})) - }, - {"zext","{{(width_out-width_in){1'b0}},in}", - - }, - {"sext","{{(width_out-width_in){in[width_in-1]}},in}", - - }, - {"strip","in", - vAST::make_id("in") - }, - {"wrap","in", - vAST::make_id("in") - }, - {"const","value", - vAST::make_id("value") - }, - {"tribuf","en ? in : 'hz", - vAST::TernaryOp( + vAST::make_id("lo")); + }}}, + {"concat",{"{in1,in0}", + [](){ return std::make_unique(make_args({"in1", "in0"})); + }}}, + {"zext",{"{{(width_out-width_in){1'b0}},in}", + [](){ + // Can't use initializer list of vector of unique ptrs, so we + // explicitly construct it + std::vector> zext_args; + zext_args.push_back( + std::make_unique( + vAST::make_binop( + vAST::make_id("width_out"), + vAST::BinOp::SUB, + vAST::make_id("width_in") + ), + std::make_unique("0", 1, false, + vAST::Radix::BINARY) + ) + ); + zext_args.push_back( + vAST::make_id("in") + ); + return std::make_unique(std::move(zext_args)); + }}}, + {"sext",{"{{(width_out-width_in){in[width_in-1]}},in}", + [](){ + // Can't use initializer list of vector of unique ptrs, so we + // explicitly construct it + std::vector> sext_args; + sext_args.push_back( + std::make_unique( + vAST::make_binop( + vAST::make_id("width_out"), + vAST::BinOp::SUB, + vAST::make_id("width_in") + ), + std::make_unique( + vAST::make_id("in"), + vAST::make_binop( + vAST::make_id("width_in"), + vAST::BinOp::SUB, + vAST::make_num("1") + ) + ) + ) + ); + sext_args.push_back(vAST::make_id("in")); + return std::make_unique(std::move(sext_args)); + }}}, + {"strip",{"in", + [](){ return vAST::make_id("in"); + }}}, + {"wrap",{"in", + [](){ return vAST::make_id("in"); + }}}, + {"const",{"value", + [](){ return vAST::make_id("value"); + }}}, + {"tribuf",{"en ? in : 'hz", + [](){ return std::make_unique( vAST::make_id("en"), vAST::make_id("in"), - std::make_unique("z", vAST::Radix::HEX)) - }, - {"ibuf","in", - vAST::make_id("in") - }, + std::make_unique("z", vAST::Radix::HEX)); + }}}, + {"ibuf",{"in", + [](){ return vAST::make_id("in"); + }}} //{"term",""} //{"reg",""}, //{"mem",""}, @@ -295,7 +317,7 @@ void CoreIRLoadVerilog_coreir(Context* c) { for (auto it0 : coreVMap) { for (auto it1 : it0.second) { string op = it1.first; - string vbody = it1.second; + string vbody = it1.second.first; json vjson; vjson["prefix"] = "coreir_"; vjson["definition"] = " assign out = " + vbody + ";"; From bcc96a9882876df15b67ada0400e015757489f5d Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Thu, 12 Dec 2019 16:11:24 -0800 Subject: [PATCH 03/20] inline basic primitives --- include/coreir/definitions/coreVerilog.hpp | 2 + include/coreir/definitions/corebitVerilog.hpp | 60 +++++-- include/coreir/ir/generator.h | 3 +- include/coreir/ir/module.h | 3 +- src/passes/analysis/verilog.cpp | 164 +++++++++++++++++- tests/gtest/test_verilog.cpp | 49 ++++++ 6 files changed, 262 insertions(+), 19 deletions(-) diff --git a/include/coreir/definitions/coreVerilog.hpp b/include/coreir/definitions/coreVerilog.hpp index 024e3f36b..22c33d08b 100644 --- a/include/coreir/definitions/coreVerilog.hpp +++ b/include/coreir/definitions/coreVerilog.hpp @@ -330,7 +330,9 @@ void CoreIRLoadVerilog_coreir(Context* c) { ASSERT(coreIMap.count(it1.first),"missing" + it1.first); vjson["interface"] = coreIMap.at(it1.first); } + vjson["primitive_type"] = it0.first; core->getGenerator(op)->getMetaData()["verilog"] = vjson; + core->getGenerator(op)->setPrimitiveExpressionLambda(it1.second.second); } } diff --git a/include/coreir/definitions/corebitVerilog.hpp b/include/coreir/definitions/corebitVerilog.hpp index a53eecc1e..34c2df736 100644 --- a/include/coreir/definitions/corebitVerilog.hpp +++ b/include/coreir/definitions/corebitVerilog.hpp @@ -3,23 +3,55 @@ using namespace CoreIR; using namespace std; void CoreIRLoadVerilog_corebit(Context* c) { - std::map> bitVMap({ + std::map()>>>> + bitVMap({ {"unary",{ - {"wire","in"}, - {"not","~in"}, + {"wire",{ + "in", + []() {return vAST::make_id("in");} + }}, + {"not",{ + "~in", + []() {return std::make_unique(vAST::make_id("in"), vAST::UnOp::INVERT);} + }} }}, {"binary",{ - {"and","in0 & in1"}, - {"or","in0 | in1"}, - {"xor","in0 ^ in1"}, + {"and",{"in0 & in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::AND, vAST::make_id("in1")); + }}}, + {"or",{"in0 | in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::OR, vAST::make_id("in1")); + }}}, + {"xor",{"in0 ^ in1", + []() {return std::make_unique(vAST::make_id("in0"), + vAST::BinOp::XOR, vAST::make_id("in1")); + }}} }}, {"other",{ - {"mux","sel ? in1 : in0"}, - {"concat","{in0, in1}"}, - {"const","value"}, - {"term",""}, - {"tribuf","en ? in : 1'bz"}, - {"ibuf","in"}, + {"mux",{"sel ? in1 : in0", + [](){ return std::make_unique( + vAST::make_id("sel"), + vAST::make_id("in1"), + vAST::make_id("in0")); + }}}, + {"concat",{"{in1,in0}", + [](){ return std::make_unique(make_args({"in1", "in0"})); + }}}, + {"const",{"value", + [](){ return vAST::make_id("value"); + }}}, + {"term",{"", [](){ return nullptr; }}}, + {"tribuf",{"en ? in : 'hz", + [](){ return std::make_unique( + vAST::make_id("en"), + vAST::make_id("in"), + std::make_unique("z", vAST::Radix::HEX)); + }}}, + {"ibuf",{"in", + [](){ return vAST::make_id("in"); + }}} }} }); @@ -73,7 +105,7 @@ void CoreIRLoadVerilog_corebit(Context* c) { for (auto it0 : bitVMap) { for (auto it1 : it0.second) { string op = it1.first; - string vbody = it1.second; + string vbody = it1.second.first; json vjson; vjson["prefix"] = "corebit_"; vjson["definition"] = " assign out = " + vbody + ";"; @@ -86,6 +118,8 @@ void CoreIRLoadVerilog_corebit(Context* c) { ASSERT(bitIMap.count(it1.first),"missing" + it1.first); vjson["interface"] = bitIMap.at(it1.first); } + vjson["primitive_type"] = it0.first; + bit->getModule(op)->setPrimitiveExpressionLambda(it1.second.second); bit->getModule(op)->getMetaData()["verilog"] = vjson; } } diff --git a/include/coreir/ir/generator.h b/include/coreir/ir/generator.h index 8bb563e9a..ddeb0d408 100644 --- a/include/coreir/ir/generator.h +++ b/include/coreir/ir/generator.h @@ -4,10 +4,11 @@ #include "fwd_declare.h" #include "globalvalue.h" +#include "coreir/primitive.h" namespace CoreIR { -class Generator : public GlobalValue { +class Generator : public GlobalValue, public Primitive { TypeGen* typegen; diff --git a/include/coreir/ir/module.h b/include/coreir/ir/module.h index 5db661ccf..4bbfff99e 100644 --- a/include/coreir/ir/module.h +++ b/include/coreir/ir/module.h @@ -5,10 +5,11 @@ #include "fwd_declare.h" #include "args.h" #include "globalvalue.h" +#include "coreir/primitive.h" namespace CoreIR { -class Module : public GlobalValue, public Args { +class Module : public GlobalValue, public Args, public Primitive { RecordType* type; ModuleDef* def = nullptr; diff --git a/src/passes/analysis/verilog.cpp b/src/passes/analysis/verilog.cpp index dc982c28c..266a34392 100644 --- a/src/passes/analysis/verilog.cpp +++ b/src/passes/analysis/verilog.cpp @@ -1,8 +1,138 @@ #include "coreir/passes/analysis/verilog.h" #include "coreir.h" #include "coreir/tools/cxxopts.h" +#include "verilogAST/transformer.hpp" #include +namespace vAST = verilogAST; + +class UnaryOpReplacer : public vAST::Transformer { + std::unique_ptr in; + public: + UnaryOpReplacer(std::unique_ptr in) : + in(std::move(in)){}; + + virtual std::unique_ptr visit( + std::unique_ptr node) { + if (auto ptr = dynamic_cast(node.get())) { + node.release(); + std::unique_ptr id(ptr); + if (id->value == "in") { + return std::move(this->in); + } + return vAST::Transformer::visit(std::move(id)); + } + return vAST::Transformer::visit(std::move(node)); + }; +}; + +class BinaryOpReplacer : public vAST::Transformer { + std::unique_ptr in0; + std::unique_ptr in1; + public: + BinaryOpReplacer(std::unique_ptr in0, + std::unique_ptr in1) : + in0(std::move(in0)), in1(std::move(in1)){}; + + virtual std::unique_ptr visit( + std::unique_ptr node) { + if (auto ptr = dynamic_cast(node.get())) { + node.release(); + std::unique_ptr id(ptr); + if (id->value == "in0") { + return std::move(this->in0); + } else if (id->value == "in1") { + return std::move(this->in1); + } + return vAST::Transformer::visit(std::move(id)); + } + return vAST::Transformer::visit(std::move(node)); + }; +}; + +bool is_inlined(std::string primitive_type, std::string name) { + return primitive_type == "binary" || primitive_type == "unary" || + (primitive_type == "other" && name == "const"); +} + +bool can_inline_binary_op(CoreIR::Module *module, bool _inline) { + if (module->isGenerated() && + module->getGenerator()->getMetaData().count("verilog") > 0) { + json verilog_json = + module->getGenerator()->getMetaData()["verilog"]; + return module->getGenerator()->hasPrimitiveExpressionLambda() && + verilog_json["primitive_type"] == "binary" && _inline; + } + return false; +} + +std::unique_ptr inline_binary_op( + std::pair instance, + std::map, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>> + verilog_connections + ) { + BinaryOpReplacer transformer( + std::visit([](auto &&value) -> std::unique_ptr { + return std::move(value); + }, std::move(verilog_connections["in0"])) , + std::visit([](auto &&value) -> std::unique_ptr { + return std::move(value); + }, std::move(verilog_connections["in1"])) + ); + return std::make_unique( + std::make_unique(instance.first + "_out"), + transformer.visit(instance.second->getModuleRef()->getGenerator()->getPrimitiveExpressionLambda()())); +} + +bool can_inline_unary_op(CoreIR::Module *module, bool _inline) { + if (module->isGenerated() && + module->getGenerator()->getMetaData().count("verilog") > 0) { + json verilog_json = + module->getGenerator()->getMetaData()["verilog"]; + return module->getGenerator()->hasPrimitiveExpressionLambda() && + verilog_json["primitive_type"] == "unary" && _inline; + } + return false; +} + +std::unique_ptr inline_unary_op( + std::pair instance, + std::map, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>> + verilog_connections + ) { + UnaryOpReplacer transformer( + std::visit([](auto &&value) -> std::unique_ptr { + return std::move(value); + }, std::move(verilog_connections["in"]))); + return std::make_unique( + std::make_unique(instance.first + "_out"), + transformer.visit(instance.second->getModuleRef()->getGenerator()->getPrimitiveExpressionLambda()())); +} + +bool can_inline_const_op(CoreIR::Module *module, bool _inline) { + if (module->isGenerated() && + module->getGenerator()->getMetaData().count("verilog") > 0) { + json verilog_json = + module->getGenerator()->getMetaData()["verilog"]; + return module->getGenerator()->hasPrimitiveExpressionLambda() && + verilog_json["primitive_type"] == "other" && + module->getName() == "const" && _inline; + } + if (module->getMetaData().count("verilog") > 0) { + json verilog_json = module->getMetaData()["verilog"]; + return module->hasPrimitiveExpressionLambda() && + verilog_json["primitive_type"] == "other" && + module->getName() == "const" && _inline; + } + return false; +} + // Unpack variant type and convert to parent type Expression std::unique_ptr convert_to_expression(std::variant, @@ -428,7 +558,8 @@ std::vector, std::unique_ptr>> compile_module_body(RecordType *module_type, std::vector connections, - std::map instances) { + std::map instances, + bool _inline) { std::vector, std::unique_ptr>> body = declare_connections(instances); @@ -515,10 +646,22 @@ compile_module_body(RecordType *module_type, convert_value(parameter.second))); } } - std::unique_ptr statement = - std::make_unique( + std::unique_ptr statement; + if (can_inline_binary_op(instance_module, _inline)) { + statement = inline_binary_op(instance, std::move(verilog_connections)); + } else if (can_inline_unary_op(instance_module, _inline)) { + statement = inline_unary_op(instance, std::move(verilog_connections)); + } else if (can_inline_const_op(instance_module, _inline)) { + ASSERT(instance_parameters[0].first->value == "value", + "expected first param to be const value"); + statement = std::make_unique( + std::make_unique(instance.first + "_out"), + std::move(instance_parameters[0].second)); + } else { + statement = std::make_unique( module_name, std::move(instance_parameters), instance_name, std::move(verilog_connections)); + } body.push_back(std::move(statement)); } // Wire the outputs of the module and inout connections @@ -554,6 +697,12 @@ vAST::Parameters compile_params(Module *module) { void Passes::Verilog::compileModule(Module *module) { if (module->getMetaData().count("verilog") > 0) { json verilog_json = module->getMetaData()["verilog"]; + if (module->hasPrimitiveExpressionLambda() && + is_inlined(verilog_json["primitive_type"], module->getName()) && + this->_inline) { + // Module is inlined + return; + } if (verilog_json.count("verilog_string") > 0) { // module is defined by a verilog string, we just emit the entire // string @@ -571,6 +720,12 @@ void Passes::Verilog::compileModule(Module *module) { // This module is an instance of generator defined as a parametrized // verilog module json verilog_json = module->getGenerator()->getMetaData()["verilog"]; + if (module->getGenerator()->hasPrimitiveExpressionLambda() && + is_inlined(verilog_json["primitive_type"], module->getName()) && + this->_inline) { + // Module is inlined + return; + } std::string name = make_name(module->getName(), verilog_json); modules.push_back(std::make_pair( @@ -595,7 +750,8 @@ void Passes::Verilog::compileModule(Module *module) { std::unique_ptr>> body = compile_module_body(module->getType(), definition->getSortedConnections(), - definition->getInstances()); + definition->getInstances(), + this->_inline); vAST::Parameters parameters = compile_params(module); diff --git a/tests/gtest/test_verilog.cpp b/tests/gtest/test_verilog.cpp index db9ba4543..d71f8917e 100644 --- a/tests/gtest/test_verilog.cpp +++ b/tests/gtest/test_verilog.cpp @@ -1,5 +1,7 @@ #include "gtest/gtest.h" #include "coreir.h" +#include "coreir/definitions/coreVerilog.hpp" +#include "coreir/definitions/corebitVerilog.hpp" #include "assert_pass.h" using namespace CoreIR; @@ -69,6 +71,53 @@ TEST(VerilogTests, TestArraySelect) { deleteContext(c); } + +TEST(VerilogTests, TestAddInline) { + Context* c = newContext(); + CoreIRLoadVerilog_coreir(c); + Module* top; + + if (!loadFromFile(c, "add.json", &top)) { + c->die(); + } + assert(top != nullptr); + c->setTop(top->getRefName()); + + const std::vector passes = { + "rungenerators", + "removebulkconnections", + "flattentypes", + "verilog --inline" + }; + c->runPasses(passes, {}); + assertPassEq(c, "add_golden.v"); + deleteContext(c); +} + + +TEST(VerilogTests, TestTwoInline) { + Context* c = newContext(); + CoreIRLoadVerilog_coreir(c); + CoreIRLoadVerilog_corebit(c); + Module* top; + + if (!loadFromFile(c, "two_ops.json", &top)) { + c->die(); + } + assert(top != nullptr); + c->setTop(top->getRefName()); + + const std::vector passes = { + "rungenerators", + "removebulkconnections", + "flattentypes", + "verilog --inline" + }; + c->runPasses(passes, {}); + assertPassEq(c, "two_ops_golden.v"); + deleteContext(c); +} + } // namespace int main(int argc, char **argv) { From b49ad83c004135045eb53bbce2a97c26162fe469 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Thu, 12 Dec 2019 16:21:39 -0800 Subject: [PATCH 04/20] Add missing files --- include/coreir/primitive.h | 23 +++++++++ tests/gtest/add.json | 26 ++++++++++ tests/gtest/add_golden.v | 6 +++ tests/gtest/two_ops.json | 94 ++++++++++++++++++++++++++++++++++++ tests/gtest/two_ops_golden.v | 28 +++++++++++ 5 files changed, 177 insertions(+) create mode 100644 include/coreir/primitive.h create mode 100644 tests/gtest/add.json create mode 100644 tests/gtest/add_golden.v create mode 100644 tests/gtest/two_ops.json create mode 100644 tests/gtest/two_ops_golden.v diff --git a/include/coreir/primitive.h b/include/coreir/primitive.h new file mode 100644 index 000000000..cdfa6dd52 --- /dev/null +++ b/include/coreir/primitive.h @@ -0,0 +1,23 @@ +#ifndef COREIR_PRIMITIVE_HPP_ +#define COREIR_PRIMITIVE_HPP_ +#include "verilogAST.hpp" +namespace vAST = verilogAST; +namespace CoreIR { +class Primitive { + std::function()> primitiveExpressionLambda = nullptr; + public: + + void setPrimitiveExpressionLambda(std::function()> lambda) { + this->primitiveExpressionLambda = lambda; + }; + + bool hasPrimitiveExpressionLambda() { + return this->primitiveExpressionLambda != nullptr; + } + + std::function()> getPrimitiveExpressionLambda() { + return this->primitiveExpressionLambda; + } +}; +} +#endif diff --git a/tests/gtest/add.json b/tests/gtest/add.json new file mode 100644 index 000000000..8ad5d0f33 --- /dev/null +++ b/tests/gtest/add.json @@ -0,0 +1,26 @@ +{"top":"global.Top", +"namespaces":{ + "global":{ + "modules":{ + "Top":{ + "type":["Record",[ + ["I0",["Array",8,"BitIn"]], + ["I1",["Array",8,"BitIn"]], + ["O",["Array",8,"Bit"]] + ]], + "instances":{ + "inst0":{ + "genref":"coreir.add", + "genargs":{"width":["Int",8]} + } + }, + "connections":[ + ["self.I0","inst0.in0"], + ["self.I1","inst0.in1"], + ["self.O","inst0.out"] + ] + } + } + } +} +} diff --git a/tests/gtest/add_golden.v b/tests/gtest/add_golden.v new file mode 100644 index 000000000..213e72e61 --- /dev/null +++ b/tests/gtest/add_golden.v @@ -0,0 +1,6 @@ +module Top (input [7:0] I0, input [7:0] I1, output [7:0] O); +wire [7:0] inst0_out; +assign inst0_out = I0 + I1; +assign O = inst0_out; +endmodule + diff --git a/tests/gtest/two_ops.json b/tests/gtest/two_ops.json new file mode 100644 index 000000000..c8dc36cb2 --- /dev/null +++ b/tests/gtest/two_ops.json @@ -0,0 +1,94 @@ +{"top":"global.test_two_ops", +"namespaces":{ + "global":{ + "modules":{ + "Add8_cin":{ + "type":["Record",[ + ["I0",["Array",8,"BitIn"]], + ["I1",["Array",8,"BitIn"]], + ["O",["Array",8,"Bit"]], + ["CIN","BitIn"] + ]], + "instances":{ + "bit_const_0_None":{ + "modref":"corebit.const", + "modargs":{"value":["Bool",false]} + }, + "inst0":{ + "genref":"coreir.add", + "genargs":{"width":["Int",8]} + }, + "inst1":{ + "genref":"coreir.add", + "genargs":{"width":["Int",8]} + } + }, + "connections":[ + ["inst1.in0.1","bit_const_0_None.out"], + ["inst1.in0.2","bit_const_0_None.out"], + ["inst1.in0.3","bit_const_0_None.out"], + ["inst1.in0.4","bit_const_0_None.out"], + ["inst1.in0.5","bit_const_0_None.out"], + ["inst1.in0.6","bit_const_0_None.out"], + ["inst1.in0.7","bit_const_0_None.out"], + ["inst1.out","inst0.in0"], + ["self.I1","inst0.in1"], + ["self.O","inst0.out"], + ["self.CIN","inst1.in0.0"], + ["self.I0","inst1.in1"] + ] + }, + "Sub8":{ + "type":["Record",[ + ["I0",["Array",8,"BitIn"]], + ["I1",["Array",8,"BitIn"]], + ["O",["Array",8,"Bit"]] + ]], + "instances":{ + "bit_const_1_None":{ + "modref":"corebit.const", + "modargs":{"value":["Bool",true]} + }, + "inst0":{ + "genref":"coreir.not", + "genargs":{"width":["Int",8]} + }, + "inst1":{ + "modref":"global.Add8_cin" + } + }, + "connections":[ + ["inst1.CIN","bit_const_1_None.out"], + ["self.I1","inst0.in"], + ["inst1.I1","inst0.out"], + ["self.I0","inst1.I0"], + ["self.O","inst1.O"] + ] + }, + "test_two_ops":{ + "type":["Record",[ + ["I0",["Array",8,"BitIn"]], + ["I1",["Array",8,"BitIn"]], + ["O",["Array",8,"Bit"]] + ]], + "instances":{ + "inst0":{ + "genref":"coreir.add", + "genargs":{"width":["Int",8]} + }, + "inst1":{ + "modref":"global.Sub8" + } + }, + "connections":[ + ["self.I0","inst0.in0"], + ["self.I1","inst0.in1"], + ["inst1.I0","inst0.out"], + ["self.I0","inst1.I1"], + ["self.O","inst1.O"] + ] + } + } + } +} +} \ No newline at end of file diff --git a/tests/gtest/two_ops_golden.v b/tests/gtest/two_ops_golden.v new file mode 100644 index 000000000..b7c6fbb00 --- /dev/null +++ b/tests/gtest/two_ops_golden.v @@ -0,0 +1,28 @@ +module Add8_cin (input CIN, input [7:0] I0, input [7:0] I1, output [7:0] O); +wire bit_const_0_None_out; +wire [7:0] inst0_out; +wire [7:0] inst1_out; +assign bit_const_0_None_out = 0; +assign inst0_out = inst1_out + I1; +assign inst1_out = ({bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,CIN}) + I0; +assign O = inst0_out; +endmodule + +module Sub8 (input [7:0] I0, input [7:0] I1, output [7:0] O); +wire bit_const_1_None_out; +wire [7:0] inst0_out; +wire [7:0] inst1_O; +assign bit_const_1_None_out = 1; +assign inst0_out = ~ I1; +Add8_cin inst1(.CIN(bit_const_1_None_out), .I0(I0), .I1(inst0_out), .O(inst1_O)); +assign O = inst1_O; +endmodule + +module test_two_ops (input [7:0] I0, input [7:0] I1, output [7:0] O); +wire [7:0] inst0_out; +wire [7:0] inst1_O; +assign inst0_out = I0 + I1; +Sub8 inst1(.I0(inst0_out), .I1(I0), .O(inst1_O)); +assign O = inst1_O; +endmodule + From c177306e8a26f6b1118dfd94059892bd4ce96e96 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Fri, 13 Dec 2019 15:58:19 -0800 Subject: [PATCH 05/20] link verilogAST in tests --- tests/unit/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/Makefile b/tests/unit/Makefile index a8071a633..0441c83e0 100755 --- a/tests/unit/Makefile +++ b/tests/unit/Makefile @@ -3,7 +3,7 @@ HOME = ../.. INCS = -I$(HOME)/include -I. LPATH = -L$(HOME)/lib -LIBS = -Wl,-rpath,$(HOME)/lib -lcoreir -lcoreirsim -lcoreir-aetherlinglib -lcoreir-commonlib +LIBS = -Wl,-rpath,$(HOME)/lib -lverilogAST -lcoreir -lcoreirsim -lcoreir-aetherlinglib -lcoreir-commonlib #LIBS = -lcoreir SRCFILES = $(wildcard [^_]*.cpp) OBJS = $(patsubst %.cpp,build/%.o,$(SRCFILES)) From ec4fedc52da45c1ed57ba6c630bccd804577bcc6 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Fri, 13 Dec 2019 15:59:53 -0800 Subject: [PATCH 06/20] Link verilogAST --- tests/simulator/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/simulator/Makefile b/tests/simulator/Makefile index 4dc520906..5228b216d 100644 --- a/tests/simulator/Makefile +++ b/tests/simulator/Makefile @@ -3,7 +3,7 @@ HOME = ../.. INCS = -I$(HOME)/include -I. LPATH = -L$(HOME)/lib -LIBS = -Wl,-rpath,$(HOME)/lib -lcoreir -lcoreirsim -lcoreir-commonlib -lcoreir-aetherlinglib -lcoreir-float +LIBS = -Wl,-rpath,$(HOME)/lib -lverilogAST -lcoreir -lcoreirsim -lcoreir-commonlib -lcoreir-aetherlinglib -lcoreir-float SRCFILES = $(wildcard [^_]*.cpp) OBJS = $(patsubst %.cpp,build/%.o,$(SRCFILES)) EXES = $(patsubst %.cpp,build/%,$(SRCFILES)) From 3f29c95ff08f7366219b2436bcd627816baeacd5 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Fri, 13 Dec 2019 16:07:08 -0800 Subject: [PATCH 07/20] Update std --- tutorial/hellocounter/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorial/hellocounter/Makefile b/tutorial/hellocounter/Makefile index bed11bbed..306b34860 100755 --- a/tutorial/hellocounter/Makefile +++ b/tutorial/hellocounter/Makefile @@ -1,5 +1,5 @@ CXX ?= g++ -CXXFLAGS = -std=c++11 -Wall -fPIC -Werror +CXXFLAGS = -std=c++17 -Wall -fPIC -Werror HOME = ../.. INCS = -I$(HOME)/include -I. From 4dc9af09d0db1393cdadcb77bd52793b830c2e65 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Tue, 17 Dec 2019 17:16:59 -0800 Subject: [PATCH 08/20] Add assign inlining logic --- src/passes/analysis/verilog.cpp | 47 +++++++++------------------------ tests/gtest/add_golden.v | 4 +-- tests/gtest/two_ops_golden.v | 18 +++---------- 3 files changed, 17 insertions(+), 52 deletions(-) diff --git a/src/passes/analysis/verilog.cpp b/src/passes/analysis/verilog.cpp index 266a34392..21cc300a9 100644 --- a/src/passes/analysis/verilog.cpp +++ b/src/passes/analysis/verilog.cpp @@ -2,6 +2,7 @@ #include "coreir.h" #include "coreir/tools/cxxopts.h" #include "verilogAST/transformer.hpp" +#include "verilogAST/assign_inliner.hpp" #include namespace vAST = verilogAST; @@ -68,20 +69,11 @@ bool can_inline_binary_op(CoreIR::Module *module, bool _inline) { std::unique_ptr inline_binary_op( std::pair instance, - std::map, - std::unique_ptr, - std::unique_ptr, - std::unique_ptr>> - verilog_connections + std::map> verilog_connections ) { - BinaryOpReplacer transformer( - std::visit([](auto &&value) -> std::unique_ptr { - return std::move(value); - }, std::move(verilog_connections["in0"])) , - std::visit([](auto &&value) -> std::unique_ptr { - return std::move(value); - }, std::move(verilog_connections["in1"])) - ); + BinaryOpReplacer transformer( + std::move(verilog_connections["in0"]), + std::move(verilog_connections["in1"])); return std::make_unique( std::make_unique(instance.first + "_out"), transformer.visit(instance.second->getModuleRef()->getGenerator()->getPrimitiveExpressionLambda()())); @@ -100,16 +92,9 @@ bool can_inline_unary_op(CoreIR::Module *module, bool _inline) { std::unique_ptr inline_unary_op( std::pair instance, - std::map, - std::unique_ptr, - std::unique_ptr, - std::unique_ptr>> - verilog_connections + std::map> verilog_connections ) { - UnaryOpReplacer transformer( - std::visit([](auto &&value) -> std::unique_ptr { - return std::move(value); - }, std::move(verilog_connections["in"]))); + UnaryOpReplacer transformer(std::move(verilog_connections["in"])); return std::make_unique( std::make_unique(instance.first + "_out"), transformer.visit(instance.second->getModuleRef()->getGenerator()->getPrimitiveExpressionLambda()())); @@ -584,11 +569,7 @@ compile_module_body(RecordType *module_type, } vAST::Parameters instance_parameters; std::string instance_name = instance.first; - std::map, - std::unique_ptr, - std::unique_ptr, - std::unique_ptr>> - verilog_connections; + std::map> verilog_connections; for (auto port : cast(instance_module->getType())->getRecord()) { if (!port.second->isInput()) { @@ -618,13 +599,8 @@ compile_module_body(RecordType *module_type, // Otherwise we just use the entry in the connection map } else { verilog_connections.insert(std::make_pair( - port.first, - std::visit([](auto &&value) -> std::variant, - std::unique_ptr, - std::unique_ptr, - std::unique_ptr> { return std::move(value); }, - convert_to_verilog_connection(entries[0].source)) - )); + port.first, + convert_to_expression(convert_to_verilog_connection(entries[0].source)))); } } // Handle module arguments @@ -759,6 +735,9 @@ void Passes::Verilog::compileModule(Module *module) { std::unique_ptr verilog_module = std::make_unique(name, std::move(ports), std::move(body), std::move(parameters)); + + vAST::AssignInliner transformer; + verilog_module = transformer.visit(std::move(verilog_module)); modules.push_back(std::make_pair(name, std::move(verilog_module))); } diff --git a/tests/gtest/add_golden.v b/tests/gtest/add_golden.v index 213e72e61..d0d44bc84 100644 --- a/tests/gtest/add_golden.v +++ b/tests/gtest/add_golden.v @@ -1,6 +1,4 @@ module Top (input [7:0] I0, input [7:0] I1, output [7:0] O); -wire [7:0] inst0_out; -assign inst0_out = I0 + I1; -assign O = inst0_out; +assign O = I0 + I1; endmodule diff --git a/tests/gtest/two_ops_golden.v b/tests/gtest/two_ops_golden.v index b7c6fbb00..cd33698ee 100644 --- a/tests/gtest/two_ops_golden.v +++ b/tests/gtest/two_ops_golden.v @@ -1,28 +1,16 @@ module Add8_cin (input CIN, input [7:0] I0, input [7:0] I1, output [7:0] O); -wire bit_const_0_None_out; -wire [7:0] inst0_out; -wire [7:0] inst1_out; -assign bit_const_0_None_out = 0; -assign inst0_out = inst1_out + I1; -assign inst1_out = ({bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,CIN}) + I0; -assign O = inst0_out; +assign O = (({0,0,0,0,0,0,0,CIN}) + I0) + I1; endmodule module Sub8 (input [7:0] I0, input [7:0] I1, output [7:0] O); -wire bit_const_1_None_out; -wire [7:0] inst0_out; wire [7:0] inst1_O; -assign bit_const_1_None_out = 1; -assign inst0_out = ~ I1; -Add8_cin inst1(.CIN(bit_const_1_None_out), .I0(I0), .I1(inst0_out), .O(inst1_O)); +Add8_cin inst1(.CIN(1), .I0(I0), .I1(~ I1), .O(inst1_O)); assign O = inst1_O; endmodule module test_two_ops (input [7:0] I0, input [7:0] I1, output [7:0] O); -wire [7:0] inst0_out; wire [7:0] inst1_O; -assign inst0_out = I0 + I1; -Sub8 inst1(.I0(inst0_out), .I1(I0), .O(inst1_O)); +Sub8 inst1(.I0(I0 + I1), .I1(I0), .O(inst1_O)); assign O = inst1_O; endmodule From c53bedbbd03f82c614be2d9cd6208f3b8b33d17e Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Tue, 17 Dec 2019 17:17:59 -0800 Subject: [PATCH 09/20] Checkout verilogast branch --- CMakeLists.txt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in index 98d3d225e..e0e3f5518 100644 --- a/CMakeLists.txt.in +++ b/CMakeLists.txt.in @@ -7,7 +7,7 @@ project(verilogAST-download NONE) include(ExternalProject) ExternalProject_Add(verilogAST GIT_REPOSITORY https://github.com/leonardt/verilogAST-cpp.git - GIT_TAG master + GIT_TAG inline-assigns SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/verilogAST-src" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/verilogAST-build" CONFIGURE_COMMAND "" From 0b0ef88ffc60fbd7a08db8c950a72a1d4d8fa836 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Tue, 17 Dec 2019 17:32:26 -0800 Subject: [PATCH 10/20] Guard inlining logic --- src/passes/analysis/verilog.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/passes/analysis/verilog.cpp b/src/passes/analysis/verilog.cpp index 91fdeb103..4f42bd61c 100644 --- a/src/passes/analysis/verilog.cpp +++ b/src/passes/analysis/verilog.cpp @@ -739,8 +739,10 @@ void Passes::Verilog::compileModule(Module *module) { std::make_unique(name, std::move(ports), std::move(body), std::move(parameters)); - vAST::AssignInliner transformer; - verilog_module = transformer.visit(std::move(verilog_module)); + if (this->_inline) { + vAST::AssignInliner transformer; + verilog_module = transformer.visit(std::move(verilog_module)); + } modules.push_back(std::make_pair(name, std::move(verilog_module))); } From 9b5a1186cae9111417cf003fa10e9a4d8a6e6c0f Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Wed, 18 Dec 2019 16:47:21 -0800 Subject: [PATCH 11/20] Inline outputs --- tests/gtest/blackbox_verilog_golden.v | 4 +--- tests/gtest/intermediate_connection_golden.v | 4 +--- tests/gtest/two_ops_golden.v | 8 ++------ 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/gtest/blackbox_verilog_golden.v b/tests/gtest/blackbox_verilog_golden.v index 1a73f59a1..464c2024f 100644 --- a/tests/gtest/blackbox_verilog_golden.v +++ b/tests/gtest/blackbox_verilog_golden.v @@ -3,8 +3,6 @@ module foo (input I, output O); assign O = I; endmodule module top (input I, output O); -wire inst0_O; -foo inst0(.I(I), .O(inst0_O)); -assign O = inst0_O; +foo inst0(.I(I), .O(O)); endmodule diff --git a/tests/gtest/intermediate_connection_golden.v b/tests/gtest/intermediate_connection_golden.v index 4a3bc3f81..e0bb1a310 100644 --- a/tests/gtest/intermediate_connection_golden.v +++ b/tests/gtest/intermediate_connection_golden.v @@ -7,10 +7,8 @@ module top (input I, inout IO0, inout IO1, output O); wire inst0_IO; wire inst0_O; wire inst1_IO; -wire inst1_O; foo inst0(.I(I), .IO(inst0_IO), .O(inst0_O)); -foo inst1(.I(inst0_O), .IO(inst1_IO), .O(inst1_O)); -assign O = inst1_O; +foo inst1(.I(inst0_O), .IO(inst1_IO), .O(O)); assign inst0_IO = inst1_IO; assign IO0 = inst0_IO; assign inst0_IO = IO1; diff --git a/tests/gtest/two_ops_golden.v b/tests/gtest/two_ops_golden.v index cd33698ee..f45f6ab1c 100644 --- a/tests/gtest/two_ops_golden.v +++ b/tests/gtest/two_ops_golden.v @@ -3,14 +3,10 @@ assign O = (({0,0,0,0,0,0,0,CIN}) + I0) + I1; endmodule module Sub8 (input [7:0] I0, input [7:0] I1, output [7:0] O); -wire [7:0] inst1_O; -Add8_cin inst1(.CIN(1), .I0(I0), .I1(~ I1), .O(inst1_O)); -assign O = inst1_O; +Add8_cin inst1(.CIN(1), .I0(I0), .I1(~ I1), .O(O)); endmodule module test_two_ops (input [7:0] I0, input [7:0] I1, output [7:0] O); -wire [7:0] inst1_O; -Sub8 inst1(.I0(I0 + I1), .I1(I0), .O(inst1_O)); -assign O = inst1_O; +Sub8 inst1(.I0(I0 + I1), .I1(I0), .O(O)); endmodule From a6a7439ee801583e099132c4485a5f2159e9c45c Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Mon, 6 Jan 2020 10:37:47 -0800 Subject: [PATCH 12/20] Rename Primitive -> VerilogPrimitive --- include/coreir/ir/generator.h | 2 +- include/coreir/ir/module.h | 2 +- include/coreir/primitive.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/coreir/ir/generator.h b/include/coreir/ir/generator.h index ddeb0d408..c9ebeb455 100644 --- a/include/coreir/ir/generator.h +++ b/include/coreir/ir/generator.h @@ -8,7 +8,7 @@ namespace CoreIR { -class Generator : public GlobalValue, public Primitive { +class Generator : public GlobalValue, public VerilogPrimitive { TypeGen* typegen; diff --git a/include/coreir/ir/module.h b/include/coreir/ir/module.h index 4bbfff99e..2c3e70cb1 100644 --- a/include/coreir/ir/module.h +++ b/include/coreir/ir/module.h @@ -9,7 +9,7 @@ namespace CoreIR { -class Module : public GlobalValue, public Args, public Primitive { +class Module : public GlobalValue, public Args, public VerilogPrimitive { RecordType* type; ModuleDef* def = nullptr; diff --git a/include/coreir/primitive.h b/include/coreir/primitive.h index cdfa6dd52..ac1ef1d9a 100644 --- a/include/coreir/primitive.h +++ b/include/coreir/primitive.h @@ -3,7 +3,7 @@ #include "verilogAST.hpp" namespace vAST = verilogAST; namespace CoreIR { -class Primitive { +class VerilogPrimitive { std::function()> primitiveExpressionLambda = nullptr; public: From 1e4ac83044044b7d490a5c02670ecdaeb34a58de Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Mon, 6 Jan 2020 10:49:52 -0800 Subject: [PATCH 13/20] Fix boolean literal codegen --- src/passes/analysis/verilog.cpp | 2 +- tests/gtest/two_ops_golden.v | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/passes/analysis/verilog.cpp b/src/passes/analysis/verilog.cpp index 4f42bd61c..728a482c8 100644 --- a/src/passes/analysis/verilog.cpp +++ b/src/passes/analysis/verilog.cpp @@ -175,7 +175,7 @@ std::unique_ptr convert_value(Value *value) { return std::make_unique(int_value->toString()); } else if (auto bool_value = dyn_cast(value)) { return std::make_unique( - std::to_string(uint(bool_value->get()))); + std::to_string(uint(bool_value->get())), 1, false, vAST::BINARY); } else if (auto bit_vector_value = dyn_cast(value)) { BitVector bit_vector = bit_vector_value->get(); return std::make_unique( diff --git a/tests/gtest/two_ops_golden.v b/tests/gtest/two_ops_golden.v index f45f6ab1c..8a9cfdd4e 100644 --- a/tests/gtest/two_ops_golden.v +++ b/tests/gtest/two_ops_golden.v @@ -1,9 +1,9 @@ module Add8_cin (input CIN, input [7:0] I0, input [7:0] I1, output [7:0] O); -assign O = (({0,0,0,0,0,0,0,CIN}) + I0) + I1; +assign O = (({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,CIN}) + I0) + I1; endmodule module Sub8 (input [7:0] I0, input [7:0] I1, output [7:0] O); -Add8_cin inst1(.CIN(1), .I0(I0), .I1(~ I1), .O(O)); +Add8_cin inst1(.CIN(1'b1), .I0(I0), .I1(~ I1), .O(O)); endmodule module test_two_ops (input [7:0] I0, input [7:0] I1, output [7:0] O); From 317aadd1ce0e8c75fa29002645bdd0059e2c37c8 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Mon, 6 Jan 2020 11:01:36 -0800 Subject: [PATCH 14/20] Use master verilogAST --- CMakeLists.txt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in index e0e3f5518..98d3d225e 100644 --- a/CMakeLists.txt.in +++ b/CMakeLists.txt.in @@ -7,7 +7,7 @@ project(verilogAST-download NONE) include(ExternalProject) ExternalProject_Add(verilogAST GIT_REPOSITORY https://github.com/leonardt/verilogAST-cpp.git - GIT_TAG inline-assigns + GIT_TAG master SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/verilogAST-src" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/verilogAST-build" CONFIGURE_COMMAND "" From 50aac95ec75a214e3ac64e2560f362e5549d6068 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Mon, 6 Jan 2020 12:07:54 -0800 Subject: [PATCH 15/20] Inline binary reduce ops --- src/passes/analysis/verilog.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/passes/analysis/verilog.cpp b/src/passes/analysis/verilog.cpp index 728a482c8..e9d704b70 100644 --- a/src/passes/analysis/verilog.cpp +++ b/src/passes/analysis/verilog.cpp @@ -53,6 +53,7 @@ class BinaryOpReplacer : public vAST::Transformer { bool is_inlined(std::string primitive_type, std::string name) { return primitive_type == "binary" || primitive_type == "unary" || + primitive_type == "binaryReduce" || (primitive_type == "other" && name == "const"); } @@ -62,7 +63,9 @@ bool can_inline_binary_op(CoreIR::Module *module, bool _inline) { json verilog_json = module->getGenerator()->getMetaData()["verilog"]; return module->getGenerator()->hasPrimitiveExpressionLambda() && - verilog_json["primitive_type"] == "binary" && _inline; + (verilog_json["primitive_type"] == "binary" || + verilog_json["primitive_type"] == "binaryReduce") + && _inline; } return false; } From 10253f1f1c476213448e01dec3e0b7f0f735e6ba Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Mon, 6 Jan 2020 13:47:52 -0800 Subject: [PATCH 16/20] Add mux inline logic/test --- CMakeLists.txt | 2 +- src/passes/analysis/verilog.cpp | 56 ++++++++++++++++++++++++++++++++- tests/gtest/mux.json | 28 +++++++++++++++++ tests/gtest/mux_golden.v | 10 ++++++ tests/gtest/test_verilog.cpp | 25 +++++++++++++++ 5 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 tests/gtest/mux.json create mode 100644 tests/gtest/mux_golden.v diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ece06649..48686f1b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,5 +72,5 @@ add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src include_directories(${CMAKE_SOURCE_DIR}/include) enable_testing() add_executable(test_verilog tests/gtest/test_verilog.cpp) -target_link_libraries(test_verilog gtest_main coreir) +target_link_libraries(test_verilog gtest_main coreir coreir-commonlib) add_test(NAME test_verilog COMMAND test_verilog WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/gtest) diff --git a/src/passes/analysis/verilog.cpp b/src/passes/analysis/verilog.cpp index e9d704b70..e491e1189 100644 --- a/src/passes/analysis/verilog.cpp +++ b/src/passes/analysis/verilog.cpp @@ -51,10 +51,38 @@ class BinaryOpReplacer : public vAST::Transformer { }; }; +class MuxReplacer : public vAST::Transformer { + std::unique_ptr in0; + std::unique_ptr in1; + std::unique_ptr sel; + public: + MuxReplacer(std::unique_ptr in0, + std::unique_ptr in1, + std::unique_ptr sel) : + in0(std::move(in0)), in1(std::move(in1)), sel(std::move(sel)){}; + + virtual std::unique_ptr visit( + std::unique_ptr node) { + if (auto ptr = dynamic_cast(node.get())) { + node.release(); + std::unique_ptr id(ptr); + if (id->value == "in0") { + return std::move(this->in0); + } else if (id->value == "in1") { + return std::move(this->in1); + } else if (id->value == "sel") { + return std::move(this->sel); + } + return vAST::Transformer::visit(std::move(id)); + } + return vAST::Transformer::visit(std::move(node)); + }; +}; + bool is_inlined(std::string primitive_type, std::string name) { return primitive_type == "binary" || primitive_type == "unary" || primitive_type == "binaryReduce" || - (primitive_type == "other" && name == "const"); + (primitive_type == "other" && (name == "const" || name == "mux")); } bool can_inline_binary_op(CoreIR::Module *module, bool _inline) { @@ -121,6 +149,30 @@ bool can_inline_const_op(CoreIR::Module *module, bool _inline) { return false; } +bool can_inline_mux_op(CoreIR::Module *module, bool _inline) { + if (module->isGenerated() && + module->getGenerator()->getMetaData().count("verilog") > 0) { + json verilog_json = + module->getGenerator()->getMetaData()["verilog"]; + return module->getGenerator()->hasPrimitiveExpressionLambda() && + verilog_json["primitive_type"] == "other" && + module->getName() == "mux" && _inline; + } + return false; +} + +std::unique_ptr inline_mux_op( + std::pair instance, + std::map> verilog_connections + ) { + MuxReplacer transformer(std::move(verilog_connections["in0"]), + std::move(verilog_connections["in1"]), + std::move(verilog_connections["sel"])); + return std::make_unique( + std::make_unique(instance.first + "_out"), + transformer.visit(instance.second->getModuleRef()->getGenerator()->getPrimitiveExpressionLambda()())); +} + // Unpack variant type and convert to parent type Expression std::unique_ptr convert_to_expression(std::variant, @@ -633,6 +685,8 @@ compile_module_body(RecordType *module_type, statement = inline_binary_op(instance, std::move(verilog_connections)); } else if (can_inline_unary_op(instance_module, _inline)) { statement = inline_unary_op(instance, std::move(verilog_connections)); + } else if (can_inline_mux_op(instance_module, _inline)) { + statement = inline_mux_op(instance, std::move(verilog_connections)); } else if (can_inline_const_op(instance_module, _inline)) { ASSERT(instance_parameters[0].first->value == "value", "expected first param to be const value"); diff --git a/tests/gtest/mux.json b/tests/gtest/mux.json new file mode 100644 index 000000000..82b392e3b --- /dev/null +++ b/tests/gtest/mux.json @@ -0,0 +1,28 @@ +{"top":"global.Mux2xNone", +"namespaces":{ + "global":{ + "modules":{ + "Mux2xNone":{ + "type":["Record",[ + ["I0","BitIn"], + ["I1","BitIn"], + ["S","BitIn"], + ["O","Bit"] + ]], + "instances":{ + "coreir_commonlib_mux2x1_inst0":{ + "genref":"commonlib.muxn", + "genargs":{"N":["Int",2], "width":["Int",1]} + } + }, + "connections":[ + ["self.I0","coreir_commonlib_mux2x1_inst0.in.data.0.0"], + ["self.I1","coreir_commonlib_mux2x1_inst0.in.data.1.0"], + ["self.S","coreir_commonlib_mux2x1_inst0.in.sel.0"], + ["self.O","coreir_commonlib_mux2x1_inst0.out.0"] + ] + } + } + } +} +} diff --git a/tests/gtest/mux_golden.v b/tests/gtest/mux_golden.v new file mode 100644 index 000000000..ccf9b9104 --- /dev/null +++ b/tests/gtest/mux_golden.v @@ -0,0 +1,10 @@ +module commonlib_muxn__N2__width1 (input [0:0] in_data_0, input [0:0] in_data_1, input [0:0] in_sel, output [0:0] out); +assign out = in_sel[0] ? in_data_1 : in_data_0; +endmodule + +module Mux2xNone (input I0, input I1, output O, input S); +wire [0:0] coreir_commonlib_mux2x1_inst0_out; +commonlib_muxn__N2__width1 coreir_commonlib_mux2x1_inst0(.in_data_0(I0), .in_data_1(I1), .in_sel(S), .out(coreir_commonlib_mux2x1_inst0_out)); +assign O = coreir_commonlib_mux2x1_inst0_out[0]; +endmodule + diff --git a/tests/gtest/test_verilog.cpp b/tests/gtest/test_verilog.cpp index d71f8917e..d71dbf321 100644 --- a/tests/gtest/test_verilog.cpp +++ b/tests/gtest/test_verilog.cpp @@ -2,6 +2,7 @@ #include "coreir.h" #include "coreir/definitions/coreVerilog.hpp" #include "coreir/definitions/corebitVerilog.hpp" +#include "coreir/libs/commonlib.h" #include "assert_pass.h" using namespace CoreIR; @@ -118,6 +119,30 @@ TEST(VerilogTests, TestTwoInline) { deleteContext(c); } +TEST(VerilogTests, TestMuxInline) { + Context* c = newContext(); + CoreIRLoadVerilog_coreir(c); + CoreIRLoadVerilog_corebit(c); + CoreIRLoadLibrary_commonlib(c); + Module* top; + + if (!loadFromFile(c, "mux.json", &top)) { + c->die(); + } + assert(top != nullptr); + c->setTop(top->getRefName()); + + const std::vector passes = { + "rungenerators", + "removebulkconnections", + "flattentypes", + "verilog --inline" + }; + c->runPasses(passes, {}); + assertPassEq(c, "mux_golden.v"); + deleteContext(c); +} + } // namespace int main(int argc, char **argv) { From 123c1c40875c9a2f18db5e7657b8fd5cfd6a29f1 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Mon, 6 Jan 2020 16:02:39 -0800 Subject: [PATCH 17/20] Inline muxes --- src/passes/analysis/verilog.cpp | 31 +++++++++++++++++++++++++++- tests/gtest/mux.json | 36 ++++++++++++++++++++++----------- tests/gtest/mux_golden.v | 24 +++++++++++++++++----- 3 files changed, 73 insertions(+), 18 deletions(-) diff --git a/src/passes/analysis/verilog.cpp b/src/passes/analysis/verilog.cpp index e491e1189..9f8d68539 100644 --- a/src/passes/analysis/verilog.cpp +++ b/src/passes/analysis/verilog.cpp @@ -82,7 +82,8 @@ class MuxReplacer : public vAST::Transformer { bool is_inlined(std::string primitive_type, std::string name) { return primitive_type == "binary" || primitive_type == "unary" || primitive_type == "binaryReduce" || - (primitive_type == "other" && (name == "const" || name == "mux")); + (primitive_type == "other" && + (name == "const" || name == "mux" || name == "slice")); } bool can_inline_binary_op(CoreIR::Module *module, bool _inline) { @@ -173,6 +174,18 @@ std::unique_ptr inline_mux_op( transformer.visit(instance.second->getModuleRef()->getGenerator()->getPrimitiveExpressionLambda()())); } +bool can_inline_slice_op(CoreIR::Module *module, bool _inline) { + if (module->isGenerated() && + module->getGenerator()->getMetaData().count("verilog") > 0) { + json verilog_json = + module->getGenerator()->getMetaData()["verilog"]; + return module->getGenerator()->hasPrimitiveExpressionLambda() && + verilog_json["primitive_type"] == "other" && + module->getName() == "slice" && _inline; + } + return false; +} + // Unpack variant type and convert to parent type Expression std::unique_ptr convert_to_expression(std::variant, @@ -693,6 +706,22 @@ compile_module_body(RecordType *module_type, statement = std::make_unique( std::make_unique(instance.first + "_out"), std::move(instance_parameters[0].second)); + } else if (can_inline_slice_op(instance_module, _inline)) { + ASSERT(instance_parameters[0].first->value == "hi", + "expected first param to be hi"); + ASSERT(instance_parameters[1].first->value == "lo", + "expected second param to be lo"); + statement = std::make_unique( + std::make_unique(instance.first + "_out"), + std::make_unique( + std::move(verilog_connections["in"]), + vAST::make_binop( + std::move(instance_parameters[0].second), + vAST::BinOp::SUB, + vAST::make_num("1") + ), + std::move(instance_parameters[1].second) + )); } else { statement = std::make_unique( module_name, std::move(instance_parameters), instance_name, diff --git a/tests/gtest/mux.json b/tests/gtest/mux.json index 82b392e3b..a1c0c9b32 100644 --- a/tests/gtest/mux.json +++ b/tests/gtest/mux.json @@ -1,25 +1,37 @@ -{"top":"global.Mux2xNone", +{"top":"global.Mux8x8", "namespaces":{ "global":{ "modules":{ - "Mux2xNone":{ + "Mux8x8":{ "type":["Record",[ - ["I0","BitIn"], - ["I1","BitIn"], - ["S","BitIn"], - ["O","Bit"] + ["I0",["Array",8,"BitIn"]], + ["I1",["Array",8,"BitIn"]], + ["I2",["Array",8,"BitIn"]], + ["I3",["Array",8,"BitIn"]], + ["I4",["Array",8,"BitIn"]], + ["I5",["Array",8,"BitIn"]], + ["I6",["Array",8,"BitIn"]], + ["I7",["Array",8,"BitIn"]], + ["S",["Array",3,"BitIn"]], + ["O",["Array",8,"Bit"]] ]], "instances":{ - "coreir_commonlib_mux2x1_inst0":{ + "coreir_commonlib_mux8x8_inst0":{ "genref":"commonlib.muxn", - "genargs":{"N":["Int",2], "width":["Int",1]} + "genargs":{"N":["Int",8], "width":["Int",8]} } }, "connections":[ - ["self.I0","coreir_commonlib_mux2x1_inst0.in.data.0.0"], - ["self.I1","coreir_commonlib_mux2x1_inst0.in.data.1.0"], - ["self.S","coreir_commonlib_mux2x1_inst0.in.sel.0"], - ["self.O","coreir_commonlib_mux2x1_inst0.out.0"] + ["self.I0","coreir_commonlib_mux8x8_inst0.in.data.0"], + ["self.I1","coreir_commonlib_mux8x8_inst0.in.data.1"], + ["self.I2","coreir_commonlib_mux8x8_inst0.in.data.2"], + ["self.I3","coreir_commonlib_mux8x8_inst0.in.data.3"], + ["self.I4","coreir_commonlib_mux8x8_inst0.in.data.4"], + ["self.I5","coreir_commonlib_mux8x8_inst0.in.data.5"], + ["self.I6","coreir_commonlib_mux8x8_inst0.in.data.6"], + ["self.I7","coreir_commonlib_mux8x8_inst0.in.data.7"], + ["self.S","coreir_commonlib_mux8x8_inst0.in.sel"], + ["self.O","coreir_commonlib_mux8x8_inst0.out"] ] } } diff --git a/tests/gtest/mux_golden.v b/tests/gtest/mux_golden.v index ccf9b9104..441223b35 100644 --- a/tests/gtest/mux_golden.v +++ b/tests/gtest/mux_golden.v @@ -1,10 +1,24 @@ -module commonlib_muxn__N2__width1 (input [0:0] in_data_0, input [0:0] in_data_1, input [0:0] in_sel, output [0:0] out); +module commonlib_muxn__N2__width8 (input [7:0] in_data_0, input [7:0] in_data_1, input [0:0] in_sel, output [7:0] out); assign out = in_sel[0] ? in_data_1 : in_data_0; endmodule -module Mux2xNone (input I0, input I1, output O, input S); -wire [0:0] coreir_commonlib_mux2x1_inst0_out; -commonlib_muxn__N2__width1 coreir_commonlib_mux2x1_inst0(.in_data_0(I0), .in_data_1(I1), .in_sel(S), .out(coreir_commonlib_mux2x1_inst0_out)); -assign O = coreir_commonlib_mux2x1_inst0_out[0]; +module commonlib_muxn__N4__width8 (input [7:0] in_data_0, input [7:0] in_data_1, input [7:0] in_data_2, input [7:0] in_data_3, input [1:0] in_sel, output [7:0] out); +wire [7:0] muxN_0_out; +wire [7:0] muxN_1_out; +commonlib_muxn__N2__width8 muxN_0(.in_data_0(in_data_0), .in_data_1(in_data_1), .in_sel(in_sel[1 - 1:0]), .out(muxN_0_out)); +commonlib_muxn__N2__width8 muxN_1(.in_data_0(in_data_2), .in_data_1(in_data_3), .in_sel(in_sel[1 - 1:0]), .out(muxN_1_out)); +assign out = in_sel[1] ? muxN_1_out : muxN_0_out; +endmodule + +module commonlib_muxn__N8__width8 (input [7:0] in_data_0, input [7:0] in_data_1, input [7:0] in_data_2, input [7:0] in_data_3, input [7:0] in_data_4, input [7:0] in_data_5, input [7:0] in_data_6, input [7:0] in_data_7, input [2:0] in_sel, output [7:0] out); +wire [7:0] muxN_0_out; +wire [7:0] muxN_1_out; +commonlib_muxn__N4__width8 muxN_0(.in_data_0(in_data_0), .in_data_1(in_data_1), .in_data_2(in_data_2), .in_data_3(in_data_3), .in_sel(in_sel[2 - 1:0]), .out(muxN_0_out)); +commonlib_muxn__N4__width8 muxN_1(.in_data_0(in_data_4), .in_data_1(in_data_5), .in_data_2(in_data_6), .in_data_3(in_data_7), .in_sel(in_sel[2 - 1:0]), .out(muxN_1_out)); +assign out = in_sel[2] ? muxN_1_out : muxN_0_out; +endmodule + +module Mux8x8 (input [7:0] I0, input [7:0] I1, input [7:0] I2, input [7:0] I3, input [7:0] I4, input [7:0] I5, input [7:0] I6, input [7:0] I7, output [7:0] O, input [2:0] S); +commonlib_muxn__N8__width8 coreir_commonlib_mux8x8_inst0(.in_data_0(I0), .in_data_1(I1), .in_data_2(I2), .in_data_3(I3), .in_data_4(I4), .in_data_5(I5), .in_data_6(I6), .in_data_7(I7), .in_sel(S), .out(O)); endmodule From e8b24ec31137332b8e9e9e26b3fae4cd515fd155 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Mon, 6 Jan 2020 16:24:01 -0800 Subject: [PATCH 18/20] Inline unary reduce --- src/passes/analysis/verilog.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/passes/analysis/verilog.cpp b/src/passes/analysis/verilog.cpp index 9f8d68539..3440b5571 100644 --- a/src/passes/analysis/verilog.cpp +++ b/src/passes/analysis/verilog.cpp @@ -81,7 +81,7 @@ class MuxReplacer : public vAST::Transformer { bool is_inlined(std::string primitive_type, std::string name) { return primitive_type == "binary" || primitive_type == "unary" || - primitive_type == "binaryReduce" || + primitive_type == "unaryReduce" || primitive_type == "binaryReduce" || (primitive_type == "other" && (name == "const" || name == "mux" || name == "slice")); } @@ -117,7 +117,9 @@ bool can_inline_unary_op(CoreIR::Module *module, bool _inline) { json verilog_json = module->getGenerator()->getMetaData()["verilog"]; return module->getGenerator()->hasPrimitiveExpressionLambda() && - verilog_json["primitive_type"] == "unary" && _inline; + (verilog_json["primitive_type"] == "unary" || + verilog_json["primitive_type"] == "unaryReduce") + && _inline; } return false; } From 838dbd6a103319daf256dfc32d447d5aa1bd76a6 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Fri, 10 Jan 2020 16:27:37 -0800 Subject: [PATCH 19/20] Support inline verilog node --- CMakeLists.txt.in | 2 +- tests/gtest/inline_verilog_golden.v | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in index 98d3d225e..a0bb2cd29 100644 --- a/CMakeLists.txt.in +++ b/CMakeLists.txt.in @@ -7,7 +7,7 @@ project(verilogAST-download NONE) include(ExternalProject) ExternalProject_Add(verilogAST GIT_REPOSITORY https://github.com/leonardt/verilogAST-cpp.git - GIT_TAG master + GIT_TAG transform-inline-verilog SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/verilogAST-src" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/verilogAST-build" CONFIGURE_COMMAND "" diff --git a/tests/gtest/inline_verilog_golden.v b/tests/gtest/inline_verilog_golden.v index aae93bd79..317cdd73a 100644 --- a/tests/gtest/inline_verilog_golden.v +++ b/tests/gtest/inline_verilog_golden.v @@ -4,9 +4,7 @@ always @(posedge CLK) begin end endmodule module Main (input CLK, input I, output O); -wire FF_inst0_O; -FF FF_inst0(.CLK(CLK), .I(I), .O(FF_inst0_O)); -assign O = FF_inst0_O; +FF FF_inst0(.CLK(CLK), .I(I), .O(O)); assert property { @(posedge CLK) I |-> ##1 O }; From c7735b7abef3a81de55c0ede5ca8e44e4221e54c Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Fri, 10 Jan 2020 16:35:11 -0800 Subject: [PATCH 20/20] Revert to master --- CMakeLists.txt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in index a0bb2cd29..98d3d225e 100644 --- a/CMakeLists.txt.in +++ b/CMakeLists.txt.in @@ -7,7 +7,7 @@ project(verilogAST-download NONE) include(ExternalProject) ExternalProject_Add(verilogAST GIT_REPOSITORY https://github.com/leonardt/verilogAST-cpp.git - GIT_TAG transform-inline-verilog + GIT_TAG master SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/verilogAST-src" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/verilogAST-build" CONFIGURE_COMMAND ""