mirror of https://github.com/XS-MLVP/picker.git
fix #24 : remove dpi set function for output signal, which case multi-driven
change clang-format line break from 80 characters to 120, and reformat the project cpp/hpp
This commit is contained in:
parent
7c0543d016
commit
3af0f4f195
|
@ -38,7 +38,7 @@ BreakBeforeBinaryOperators: NonAssignment
|
|||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 80
|
||||
ColumnLimit: 120
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
|
|
|
@ -4,8 +4,7 @@ int64_t random_int64()
|
|||
{
|
||||
static std::random_device rd;
|
||||
static std::mt19937_64 generator(rd());
|
||||
static std::uniform_int_distribution<int64_t> distribution(INT64_MIN,
|
||||
INT64_MAX);
|
||||
static std::uniform_int_distribution<int64_t> distribution(INT64_MIN, INT64_MAX);
|
||||
return distribution(generator);
|
||||
}
|
||||
|
||||
|
@ -51,13 +50,12 @@ int main()
|
|||
carry = carry || sum < i.cin;
|
||||
|
||||
o_ref.sum = sum;
|
||||
o_ref.cout = carry ;
|
||||
o_ref.cout = carry;
|
||||
};
|
||||
|
||||
dut_cal();
|
||||
ref_cal();
|
||||
printf("[cycle %lu] a=0x%lx, b=0x%lx, cin=0x%lx\n", dut->xclock.clk, i.a,
|
||||
i.b, i.cin);
|
||||
printf("[cycle %lu] a=0x%lx, b=0x%lx, cin=0x%lx\n", dut->xclock.clk, i.a, i.b, i.cin);
|
||||
printf("DUT: sum=0x%lx, cout=0x%lx\n", o_dut.sum, o_dut.cout);
|
||||
printf("REF: sum=0x%lx, cout=0x%lx\n", o_ref.sum, o_ref.cout);
|
||||
Assert(o_dut.sum == o_ref.sum, "sum mismatch");
|
||||
|
|
|
@ -7,23 +7,24 @@
|
|||
#include <functional>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
class StackModel {
|
||||
class StackModel
|
||||
{
|
||||
public:
|
||||
void commitPush(int data) {
|
||||
void commitPush(int data)
|
||||
{
|
||||
stack.push_back(data);
|
||||
std::cout << "push " << data << std::endl;
|
||||
}
|
||||
|
||||
void commitPop(int dutData) {
|
||||
void commitPop(int dutData)
|
||||
{
|
||||
std::cout << "Pop " << dutData << std::endl;
|
||||
if (stack.empty()) {
|
||||
throw std::runtime_error("Stack is empty");
|
||||
}
|
||||
if (stack.empty()) { throw std::runtime_error("Stack is empty"); }
|
||||
int modelData = stack.back();
|
||||
stack.pop_back();
|
||||
if (modelData != dutData) {
|
||||
throw std::runtime_error("The model data " + std::to_string(modelData) + " is not equal to the dut data " + std::to_string(dutData));
|
||||
throw std::runtime_error("The model data " + std::to_string(modelData) + " is not equal to the dut data "
|
||||
+ std::to_string(dutData));
|
||||
}
|
||||
std::cout << "Pass: " << modelData << " == " << dutData << std::endl;
|
||||
}
|
||||
|
@ -32,104 +33,113 @@ private:
|
|||
std::vector<int> stack;
|
||||
};
|
||||
|
||||
class SinglePortDriver {
|
||||
class SinglePortDriver
|
||||
{
|
||||
public:
|
||||
enum class Status {
|
||||
IDLE, WAIT_REQ_READY, WAIT_RESP_VALID
|
||||
};
|
||||
enum class Status { IDLE, WAIT_REQ_READY, WAIT_RESP_VALID };
|
||||
|
||||
enum class BusCMD {
|
||||
PUSH, POP, PUSH_OKAY, POP_OKAY
|
||||
};
|
||||
enum class BusCMD { PUSH, POP, PUSH_OKAY, POP_OKAY };
|
||||
|
||||
SinglePortDriver(UTdual_port_stack* dut, StackModel* model, std::unordered_map<std::string, XData*> pinMap)
|
||||
: dut(dut), model(model), status(Status::IDLE), operationNum(0), remainingDelay(0), random(std::random_device{}()), pinMap(pinMap) {}
|
||||
SinglePortDriver(UTdual_port_stack *dut, StackModel *model, std::unordered_map<std::string, XData *> pinMap) :
|
||||
dut(dut),
|
||||
model(model),
|
||||
status(Status::IDLE),
|
||||
operationNum(0),
|
||||
remainingDelay(0),
|
||||
random(std::random_device{}()),
|
||||
pinMap(pinMap)
|
||||
{}
|
||||
|
||||
void push() {
|
||||
void push()
|
||||
{
|
||||
pinMap["in_valid"]->Set(1);
|
||||
pinMap["in_cmd"]->Set(static_cast<int>(BusCMD::PUSH));
|
||||
pinMap["in_data"]->Set(random() & 0xff);
|
||||
}
|
||||
|
||||
void pop() {
|
||||
void pop()
|
||||
{
|
||||
pinMap["in_valid"]->Set(1);
|
||||
pinMap["in_cmd"]->Set(static_cast<int>(BusCMD::POP));
|
||||
}
|
||||
|
||||
void stepCallback(long cycle) {
|
||||
void stepCallback(long cycle)
|
||||
{
|
||||
switch (status) {
|
||||
case Status::WAIT_REQ_READY:
|
||||
if (pinMap["in_ready"]->U() == 1) {
|
||||
pinMap["in_valid"]->Set(0);
|
||||
pinMap["out_ready"]->Set(1);
|
||||
status = Status::WAIT_RESP_VALID;
|
||||
if (pinMap["in_cmd"]->U() == static_cast<int>(BusCMD::PUSH)) {
|
||||
model->commitPush(pinMap["in_data"]->AsInt32());
|
||||
}
|
||||
case Status::WAIT_REQ_READY:
|
||||
if (pinMap["in_ready"]->U() == 1) {
|
||||
pinMap["in_valid"]->Set(0);
|
||||
pinMap["out_ready"]->Set(1);
|
||||
status = Status::WAIT_RESP_VALID;
|
||||
if (pinMap["in_cmd"]->U() == static_cast<int>(BusCMD::PUSH)) {
|
||||
model->commitPush(pinMap["in_data"]->AsInt32());
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Status::WAIT_RESP_VALID:
|
||||
if (pinMap["out_valid"]->U() == 1) {
|
||||
pinMap["out_ready"]->Set(0);
|
||||
status = Status::IDLE;
|
||||
remainingDelay = random() % 6;
|
||||
if (pinMap["out_cmd"]->U() == static_cast<int>(BusCMD::POP_OKAY)) {
|
||||
model->commitPop(pinMap["out_data"]->AsInt32());
|
||||
}
|
||||
case Status::WAIT_RESP_VALID:
|
||||
if (pinMap["out_valid"]->U() == 1) {
|
||||
pinMap["out_ready"]->Set(0);
|
||||
status = Status::IDLE;
|
||||
remainingDelay = random() % 6;
|
||||
if (pinMap["out_cmd"]->U() == static_cast<int>(BusCMD::POP_OKAY)) {
|
||||
model->commitPop(pinMap["out_data"]->AsInt32());
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Status::IDLE:
|
||||
if (remainingDelay == 0) {
|
||||
if (operationNum < 10) {
|
||||
push();
|
||||
} else if (operationNum < 20) {
|
||||
pop();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
operationNum++;
|
||||
status = Status::WAIT_REQ_READY;
|
||||
case Status::IDLE:
|
||||
if (remainingDelay == 0) {
|
||||
if (operationNum < 10) {
|
||||
push();
|
||||
} else if (operationNum < 20) {
|
||||
pop();
|
||||
} else {
|
||||
remainingDelay--;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
operationNum++;
|
||||
status = Status::WAIT_REQ_READY;
|
||||
} else {
|
||||
remainingDelay--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
UTdual_port_stack* dut;
|
||||
StackModel* model;
|
||||
UTdual_port_stack *dut;
|
||||
StackModel *model;
|
||||
Status status;
|
||||
int operationNum;
|
||||
int remainingDelay;
|
||||
std::mt19937 random;
|
||||
std::unordered_map<std::string, XData*> pinMap;
|
||||
std::unordered_map<std::string, XData *> pinMap;
|
||||
};
|
||||
|
||||
void testStack(UTdual_port_stack* stack) {
|
||||
void testStack(UTdual_port_stack *stack)
|
||||
{
|
||||
StackModel model;
|
||||
std::unordered_map<std::string, XData*> pinMap0 = {
|
||||
{"in_valid", &stack->in0_valid}, {"in_ready", &stack->in0_ready}, {"in_data", &stack->in0_data}, {"in_cmd", &stack->in0_cmd},
|
||||
{"out_valid", &stack->out0_valid}, {"out_ready", &stack->out0_ready}, {"out_data", &stack->out0_data}, {"out_cmd", &stack->out0_cmd}
|
||||
};
|
||||
std::unordered_map<std::string, XData *> pinMap0 = {
|
||||
{"in_valid", &stack->in0_valid}, {"in_ready", &stack->in0_ready}, {"in_data", &stack->in0_data},
|
||||
{"in_cmd", &stack->in0_cmd}, {"out_valid", &stack->out0_valid}, {"out_ready", &stack->out0_ready},
|
||||
{"out_data", &stack->out0_data}, {"out_cmd", &stack->out0_cmd}};
|
||||
|
||||
std::unordered_map<std::string, XData*> pinMap1 = {
|
||||
{"in_valid", &stack->in1_valid}, {"in_ready", &stack->in1_ready}, {"in_data", &stack->in1_data}, {"in_cmd", &stack->in1_cmd},
|
||||
{"out_valid", &stack->out1_valid}, {"out_ready", &stack->out1_ready}, {"out_data", &stack->out1_data}, {"out_cmd", &stack->out1_cmd}
|
||||
};
|
||||
std::unordered_map<std::string, XData *> pinMap1 = {
|
||||
{"in_valid", &stack->in1_valid}, {"in_ready", &stack->in1_ready}, {"in_data", &stack->in1_data},
|
||||
{"in_cmd", &stack->in1_cmd}, {"out_valid", &stack->out1_valid}, {"out_ready", &stack->out1_ready},
|
||||
{"out_data", &stack->out1_data}, {"out_cmd", &stack->out1_cmd}};
|
||||
|
||||
SinglePortDriver driver0(stack, &model, pinMap0);
|
||||
SinglePortDriver driver1(stack, &model, pinMap1);
|
||||
|
||||
stack->StepRis([&driver0](long cycle, void*) { driver0.stepCallback(cycle); });
|
||||
stack->StepRis([&driver1](long cycle, void*) { driver1.stepCallback(cycle); });
|
||||
stack->StepRis([&driver0](long cycle, void *) { driver0.stepCallback(cycle); });
|
||||
stack->StepRis([&driver1](long cycle, void *) { driver1.stepCallback(cycle); });
|
||||
stack->Step(200);
|
||||
printf("C++ Test Passed\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main()
|
||||
{
|
||||
UTdual_port_stack dut;
|
||||
dut.InitClock("clk");
|
||||
testStack(&dut);
|
||||
|
|
|
@ -4,20 +4,19 @@ int64_t random_int64()
|
|||
{
|
||||
static std::random_device rd;
|
||||
static std::mt19937_64 generator(rd());
|
||||
static std::uniform_int_distribution<int64_t> distribution(INT64_MIN,
|
||||
INT64_MAX);
|
||||
static std::uniform_int_distribution<int64_t> distribution(INT64_MIN, INT64_MAX);
|
||||
return distribution(generator);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
UTRandomGenerator *dut = new UTRandomGenerator();
|
||||
unsigned short seed = random_int64() & 0xffff;
|
||||
unsigned short seed = random_int64() & 0xffff;
|
||||
printf("seed = 0x%x\n", seed);
|
||||
dut->InitClock(dut->clk);
|
||||
dut->Step(10);
|
||||
dut->reset = 1;
|
||||
dut->seed = seed;
|
||||
dut->seed = seed;
|
||||
dut->Step(1);
|
||||
dut->reset = 0;
|
||||
dut->Step(1);
|
||||
|
@ -28,7 +27,6 @@ int main()
|
|||
};
|
||||
|
||||
for (int c = 0; c < 114514; c++) {
|
||||
|
||||
output_t o_dut, o_ref;
|
||||
|
||||
auto dut_cal = [&]() {
|
||||
|
@ -37,8 +35,8 @@ int main()
|
|||
};
|
||||
|
||||
// as lfsr
|
||||
auto ref_cal = [&]() {
|
||||
seed = (seed << 1) | ((seed >> 15) ^ (seed >> 14) & 1);
|
||||
auto ref_cal = [&]() {
|
||||
seed = (seed << 1) | ((seed >> 15) ^ (seed >> 14) & 1);
|
||||
o_ref.cout = seed;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,13 +5,10 @@
|
|||
#include "parser/sv.hpp"
|
||||
|
||||
namespace picker {
|
||||
std::string replace_all(std::string str, const std::string &from,
|
||||
const std::string &to);
|
||||
std::string replace_all(std::string str, const std::string &from, const std::string &to);
|
||||
|
||||
namespace codegen {
|
||||
void cpp(picker::export_opts& opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal,
|
||||
nlohmann::json &signal_tree_json);
|
||||
void cpp(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json);
|
||||
} // namespace codegen
|
||||
} // namespace picker
|
|
@ -5,8 +5,6 @@
|
|||
#include "parser/sv.hpp"
|
||||
|
||||
namespace picker { namespace codegen {
|
||||
void golang(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal,
|
||||
nlohmann::json &signal_tree_json);
|
||||
void golang(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json);
|
||||
}} // namespace picker::codegen
|
|
@ -5,8 +5,6 @@
|
|||
#include "parser/sv.hpp"
|
||||
|
||||
namespace picker { namespace codegen {
|
||||
void java(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal,
|
||||
nlohmann::json &signal_tree_json);
|
||||
void java(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json);
|
||||
}} // namespace picker::codegen
|
|
@ -11,15 +11,14 @@ namespace picker { namespace codegen {
|
|||
/// @param dst_dir
|
||||
/// @param data
|
||||
/// @param env
|
||||
void recursive_render(std::string &src_dir, std::string &dst_dir,
|
||||
nlohmann::json &data, inja::Environment &env);
|
||||
void recursive_render(std::string &src_dir, std::string &dst_dir, nlohmann::json &data, inja::Environment &env);
|
||||
|
||||
/// @brief render all svdpi files, build related files and copy other files
|
||||
/// @param opts
|
||||
/// @param external_pin
|
||||
/// @param internal_pin
|
||||
std::vector<picker::sv_signal_define> lib(picker::export_opts &opts,
|
||||
const std::vector<picker::sv_module_define> sv_module_result,
|
||||
const std::vector<picker::sv_signal_define> &internal_pin,
|
||||
nlohmann::json &signal_tree_json);
|
||||
const std::vector<picker::sv_module_define> sv_module_result,
|
||||
const std::vector<picker::sv_signal_define> &internal_pin,
|
||||
nlohmann::json &signal_tree_json);
|
||||
}} // namespace picker::codegen
|
|
@ -5,8 +5,6 @@
|
|||
#include "parser/sv.hpp"
|
||||
|
||||
namespace picker { namespace codegen {
|
||||
void python(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal,
|
||||
nlohmann::json &signal_tree_json);
|
||||
void python(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json);
|
||||
}} // namespace picker::codegen
|
|
@ -5,8 +5,6 @@
|
|||
#include "parser/sv.hpp"
|
||||
|
||||
namespace picker { namespace codegen {
|
||||
void scala(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal,
|
||||
nlohmann::json &signal_tree_json);
|
||||
void scala(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json);
|
||||
}} // namespace picker::codegen
|
|
@ -6,10 +6,9 @@
|
|||
|
||||
namespace picker { namespace codegen {
|
||||
std::vector<picker::sv_signal_define> gen_sv_param(nlohmann::json &global_render_data,
|
||||
const std::vector<picker::sv_module_define> &sv_module_result,
|
||||
const std::vector<picker::sv_signal_define> &internal_signal,
|
||||
nlohmann::json &signal_tree_json,
|
||||
const std::string &wave_file_name,
|
||||
const std::string &simulator);
|
||||
void gen_uvm_param(picker::pack_opts &opts, uvm_transaction_define transaction,std::string filename);
|
||||
const std::vector<picker::sv_module_define> &sv_module_result,
|
||||
const std::vector<picker::sv_signal_define> &internal_signal,
|
||||
nlohmann::json &signal_tree_json,
|
||||
const std::string &wave_file_name, const std::string &simulator);
|
||||
void gen_uvm_param(picker::pack_opts &opts, uvm_transaction_define transaction, std::string filename);
|
||||
}} // namespace picker::codegen
|
|
@ -7,10 +7,7 @@
|
|||
|
||||
namespace picker { namespace parser {
|
||||
std::vector<picker::sv_signal_define> internal(std::string internal_pin_filename);
|
||||
int internal(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> &internal_pin);
|
||||
void recursive_parse(YAML::Node node,
|
||||
std::vector<picker::sv_signal_define> &pin_list,
|
||||
std::string prefix = "");
|
||||
int internal(picker::export_opts &opts, std::vector<picker::sv_signal_define> &internal_pin);
|
||||
void recursive_parse(YAML::Node node, std::vector<picker::sv_signal_define> &pin_list, std::string prefix = "");
|
||||
|
||||
}; } // namespace picker::parser
|
|
@ -3,10 +3,7 @@
|
|||
#include <bits/stdc++.h>
|
||||
#include "picker.hpp"
|
||||
|
||||
namespace picker {
|
||||
|
||||
namespace parser {
|
||||
namespace picker { namespace parser {
|
||||
int sv(picker::export_opts &opts, std::vector<picker::sv_module_define> &external_pin);
|
||||
int uvm(picker::pack_opts &opts, std::string &path, std::string &filename, uvm_transaction_define &uvm_transaction);
|
||||
};
|
||||
} // namespace pickerc
|
||||
int uvm(picker::pack_opts &opts, std::string &path, std::string &filename, uvm_transaction_define &uvm_transaction);
|
||||
}; } // namespace picker::parser
|
|
@ -27,40 +27,39 @@
|
|||
namespace picker {
|
||||
|
||||
extern bool is_debug;
|
||||
extern char* lib_random_hash;
|
||||
extern char *lib_random_hash;
|
||||
|
||||
#define PK_OUTPUT(o, fmt, ...) \
|
||||
{ \
|
||||
fprintf(o, fmt, ##__VA_ARGS__); \
|
||||
#define PK_OUTPUT(o, fmt, ...) \
|
||||
{ \
|
||||
fprintf(o, fmt, ##__VA_ARGS__); \
|
||||
}
|
||||
#define PK_MESSAGE(fmt, ...) \
|
||||
{ \
|
||||
PK_OUTPUT(stdout, fmt, ##__VA_ARGS__); \
|
||||
PK_OUTPUT(stdout, "%s\n", ""); \
|
||||
#define PK_MESSAGE(fmt, ...) \
|
||||
{ \
|
||||
PK_OUTPUT(stdout, fmt, ##__VA_ARGS__); \
|
||||
PK_OUTPUT(stdout, "%s\n", ""); \
|
||||
}
|
||||
#define PK_ERROR(fmt, ...) \
|
||||
{ \
|
||||
PK_OUTPUT(stderr, "%s", "\033[31m") \
|
||||
PK_OUTPUT(stderr, fmt, ##__VA_ARGS__) \
|
||||
PK_OUTPUT(stderr, "%s\n", "\033[0m") \
|
||||
#define PK_ERROR(fmt, ...) \
|
||||
{ \
|
||||
PK_OUTPUT(stderr, "%s", "\033[31m") \
|
||||
PK_OUTPUT(stderr, fmt, ##__VA_ARGS__) \
|
||||
PK_OUTPUT(stderr, "%s\n", "\033[0m") \
|
||||
}
|
||||
#define PK_DEBUG(fmt, ...) \
|
||||
{ \
|
||||
if (is_debug) { \
|
||||
PK_OUTPUT(stderr, "%s", "debug> "); \
|
||||
PK_OUTPUT(stderr, fmt, ##__VA_ARGS__); \
|
||||
PK_OUTPUT(stderr, "%s\n", "") \
|
||||
} \
|
||||
#define PK_DEBUG(fmt, ...) \
|
||||
{ \
|
||||
if (is_debug) { \
|
||||
PK_OUTPUT(stderr, "%s", "debug> "); \
|
||||
PK_OUTPUT(stderr, fmt, ##__VA_ARGS__); \
|
||||
PK_OUTPUT(stderr, "%s\n", "") \
|
||||
} \
|
||||
}
|
||||
#define PK_FATAL(fmt, ...) \
|
||||
{ \
|
||||
PK_OUTPUT(stderr, "%sFatal: ", "\033[31m") \
|
||||
PK_OUTPUT(stderr, fmt, ##__VA_ARGS__); \
|
||||
PK_OUTPUT(stderr, "%s\n", "\033[0m") \
|
||||
exit(-1); \
|
||||
#define PK_FATAL(fmt, ...) \
|
||||
{ \
|
||||
PK_OUTPUT(stderr, "%sFatal: ", "\033[31m") \
|
||||
PK_OUTPUT(stderr, fmt, ##__VA_ARGS__); \
|
||||
PK_OUTPUT(stderr, "%s\n", "\033[0m") \
|
||||
exit(-1); \
|
||||
}
|
||||
|
||||
|
||||
inline void vassert(bool c, std::string msg = "")
|
||||
{
|
||||
if (!c) { PK_FATAL("Assert error: %s", msg.c_str()); }
|
||||
|
@ -88,9 +87,7 @@ inline std::string exec(const char *cmd)
|
|||
std::string result;
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
|
||||
if (!pipe) { throw std::runtime_error("popen() failed!"); }
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { result += buffer.data(); }
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -102,21 +99,20 @@ inline std::string trim(std::string s, std::string p)
|
|||
return s;
|
||||
}
|
||||
|
||||
inline std::string ltrim(std::string s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}));
|
||||
inline std::string ltrim(std::string s)
|
||||
{
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string rtrim(std::string s) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}).base(), s.end());
|
||||
inline std::string rtrim(std::string s)
|
||||
{
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string trim(std::string s) {
|
||||
inline std::string trim(std::string s)
|
||||
{
|
||||
return rtrim(ltrim(s));
|
||||
}
|
||||
|
||||
|
@ -141,52 +137,45 @@ inline std::vector<std::string> strsplit(std::string str, std::string s = " ")
|
|||
inline std::string lower_case(std::string input)
|
||||
{
|
||||
auto str = input;
|
||||
std::transform(str.begin(), str.end(), str.begin(),
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
return str;
|
||||
}
|
||||
|
||||
inline std::string capitalize_first_letter(const std::string &input) {
|
||||
if (input.empty()) {
|
||||
return input;
|
||||
}
|
||||
|
||||
inline std::string capitalize_first_letter(const std::string &input)
|
||||
{
|
||||
if (input.empty()) { return input; }
|
||||
|
||||
std::string result = input;
|
||||
result[0] = std::toupper(result[0]);
|
||||
result[0] = std::toupper(result[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::map<std::string, std::string> get_default_confilct_map() {
|
||||
inline std::map<std::string, std::string> get_default_confilct_map()
|
||||
{
|
||||
std::map<std::string, std::string> pin_map;
|
||||
std::vector<std::string> conflict_pin = {"xclock", "xport", "dut", "initclock", "step", "stepris", "stepfal", "setwaveform", "setcoverage", "finish", "refreshcomb"};
|
||||
for (auto &p : conflict_pin) {
|
||||
pin_map[p] = "pin_";
|
||||
}
|
||||
std::vector<std::string> conflict_pin = {"xclock", "xport", "dut", "initclock",
|
||||
"step", "stepris", "stepfal", "setwaveform",
|
||||
"setcoverage", "finish", "refreshcomb"};
|
||||
for (auto &p : conflict_pin) { pin_map[p] = "pin_"; }
|
||||
return pin_map;
|
||||
}
|
||||
|
||||
inline std::string fix_conflict_pin_name(const std::string &in, std::map<std::string, std::string> &pin_map, bool cap_first = false) {
|
||||
inline std::string fix_conflict_pin_name(const std::string &in, std::map<std::string, std::string> &pin_map,
|
||||
bool cap_first = false)
|
||||
{
|
||||
auto input = lower_case(in);
|
||||
if(input.empty()){
|
||||
PK_FATAL("input pin name is empty");
|
||||
}
|
||||
if (input.empty()) { PK_FATAL("input pin name is empty"); }
|
||||
// not find in conflict map
|
||||
if (pin_map.find(input) == pin_map.end()) {
|
||||
if (cap_first) {
|
||||
return capitalize_first_letter(in);
|
||||
}
|
||||
if (cap_first) { return capitalize_first_letter(in); }
|
||||
return in;
|
||||
}
|
||||
std::string result = pin_map[input] + in;
|
||||
if (cap_first) {
|
||||
result = capitalize_first_letter(result);
|
||||
}
|
||||
if (cap_first) { result = capitalize_first_letter(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::string strsplit(std::string str,
|
||||
std::initializer_list<std::string> s,
|
||||
bool front = true)
|
||||
inline std::string strsplit(std::string str, std::initializer_list<std::string> s, bool front = true)
|
||||
{
|
||||
auto ret = str;
|
||||
for (auto &v : s) {
|
||||
|
@ -217,9 +206,7 @@ inline std::string streplace(std::string str, std::string s, std::string t = "")
|
|||
return input;
|
||||
}
|
||||
|
||||
inline std::string streplace(std::string str,
|
||||
std::initializer_list<std::string> s,
|
||||
std::string t = "")
|
||||
inline std::string streplace(std::string str, std::initializer_list<std::string> s, std::string t = "")
|
||||
{
|
||||
auto ret = str;
|
||||
for (auto &v : s) { ret = streplace(ret, v, t); }
|
||||
|
@ -236,20 +223,18 @@ inline bool contians(std::vector<T> v, T a)
|
|||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
inline std::vector<T> key_as_vector(std::map<T, F> &input){
|
||||
inline std::vector<T> key_as_vector(std::map<T, F> &input)
|
||||
{
|
||||
std::vector<T> keys;
|
||||
for (const auto& pair : input) {
|
||||
keys.push_back(pair.first);
|
||||
}
|
||||
for (const auto &pair : input) { keys.push_back(pair.first); }
|
||||
return keys;
|
||||
}
|
||||
|
||||
inline std::string join_str_vec(const std::vector<std::string>& strings, const std::string& delimiter) {
|
||||
inline std::string join_str_vec(const std::vector<std::string> &strings, const std::string &delimiter)
|
||||
{
|
||||
if (strings.empty()) return "";
|
||||
std::string result = strings[0];
|
||||
for (size_t i = 1; i < strings.size(); ++i) {
|
||||
result += delimiter + strings[i];
|
||||
}
|
||||
for (size_t i = 1; i < strings.size(); ++i) { result += delimiter + strings[i]; }
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -265,7 +250,6 @@ inline std::string exec_result(std::string cmd, int index)
|
|||
return result[index];
|
||||
}
|
||||
|
||||
|
||||
inline std::string first_upercase(std::string input)
|
||||
{
|
||||
std::string ret = input;
|
||||
|
@ -316,8 +300,7 @@ inline std::string current_path()
|
|||
template <typename... Args>
|
||||
std::string sfmt(const std::string &format, Args... args)
|
||||
{
|
||||
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...)
|
||||
+ 1; // Extra space for '\0'
|
||||
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
||||
if (size_s <= 0) { throw std::runtime_error("Error during formatting."); }
|
||||
auto size = static_cast<size_t>(size_s);
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
|
@ -388,8 +371,7 @@ inline std::string read_params(std::string fname)
|
|||
return ret;
|
||||
};
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) \
|
||||
|| defined(__WIN32) && !defined(__CYGWIN__)
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
|
||||
inline std::string get_executable_path()
|
||||
|
@ -434,7 +416,8 @@ inline bool str_start_with(std::string str, std::string prefix)
|
|||
return str.find(prefix) == 0;
|
||||
}
|
||||
|
||||
inline bool str_start_with_digit(const std::string& str) {
|
||||
inline bool str_start_with_digit(const std::string &str)
|
||||
{
|
||||
if (str.empty()) return false;
|
||||
return std::isdigit(str[0]);
|
||||
}
|
||||
|
@ -442,14 +425,10 @@ inline bool str_start_with_digit(const std::string& str) {
|
|||
inline std::string get_target_path_from(std::string base, std::vector<std::string> paths)
|
||||
{
|
||||
auto path = get_executable_path();
|
||||
for (auto &l: paths){
|
||||
for (auto &l : paths) {
|
||||
auto p = std::string(l);
|
||||
if(!str_start_with(p, "/")){
|
||||
p = path_join({base, p});
|
||||
}
|
||||
if(file_exists(p)){
|
||||
return p;
|
||||
}
|
||||
if (!str_start_with(p, "/")) { p = path_join({base, p}); }
|
||||
if (file_exists(p)) { return p; }
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -459,26 +438,26 @@ inline std::string get_target_path_from(std::string base, std::initializer_list<
|
|||
return get_target_path_from(base, std::vector<std::string>(paths));
|
||||
}
|
||||
|
||||
inline std::string get_xcomm_location(){
|
||||
inline std::string get_xcomm_location()
|
||||
{
|
||||
auto path = get_executable_path();
|
||||
return get_target_path_from(path, {"../../dependence/xcomm", // 1. search in bulid dir (for dev)
|
||||
"./picker", // 2. search in current dir
|
||||
"../../share/picker", // 3. search in share dir (for install)
|
||||
"/usr/local/share/picker", // 4. search in /usr/local/share
|
||||
"/usr/share/picker", // 5. search in /usr/share
|
||||
"/etc/picker"}); // 6. search in /etc
|
||||
return get_target_path_from(path, {"../../dependence/xcomm", // 1. search in bulid dir (for dev)
|
||||
"./picker", // 2. search in current dir
|
||||
"../../share/picker", // 3. search in share dir (for install)
|
||||
"/usr/local/share/picker", // 4. search in /usr/local/share
|
||||
"/usr/share/picker", // 5. search in /usr/share
|
||||
"/etc/picker"}); // 6. search in /etc
|
||||
}
|
||||
|
||||
inline std::string get_xcomm_lib(std::string lib_name, std::string & message){
|
||||
inline std::string get_xcomm_lib(std::string lib_name, std::string &message)
|
||||
{
|
||||
auto path = get_xcomm_location();
|
||||
if(path.empty()){
|
||||
if (path.empty()) {
|
||||
message = "xcomm lib not found";
|
||||
return "";
|
||||
}
|
||||
auto lib = path_join({path, lib_name});
|
||||
if(file_exists(lib)){
|
||||
return lib;
|
||||
}
|
||||
if (file_exists(lib)) { return lib; }
|
||||
message = lib + " not found";
|
||||
return "";
|
||||
}
|
||||
|
@ -486,30 +465,30 @@ inline std::string get_xcomm_lib(std::string lib_name, std::string & message){
|
|||
inline std::string get_template_path()
|
||||
{
|
||||
auto path = get_executable_path();
|
||||
auto tmp = get_target_path_from(path, {"../../../template", // 1. search in source dir (for dev)
|
||||
auto tmp = get_target_path_from(path, {"../../../template", // 1. search in source dir (for dev)
|
||||
"./template", // 2. search in current dir
|
||||
"../../share/picker/template", // 3. search in share dir (for install)
|
||||
"/usr/local/share/picker/template", // 4. search in /usr/local/share
|
||||
"/etc/picker/template"}); // 5. search in /etc
|
||||
if(!tmp.empty()){
|
||||
return tmp;
|
||||
}
|
||||
if (!tmp.empty()) { return tmp; }
|
||||
PK_FATAL("template not found, please check the installation or mannualy set the source dir path");
|
||||
}
|
||||
inline std::string extract_name(const std::string& input, char delimiter,int isFirst) {
|
||||
inline std::string extract_name(const std::string &input, char delimiter, int isFirst)
|
||||
{
|
||||
size_t pos = input.find(delimiter);
|
||||
if(pos != std::string::npos){
|
||||
if (pos != std::string::npos) {
|
||||
if (isFirst == 1) {
|
||||
return input.substr(0, pos);
|
||||
}else{
|
||||
} else {
|
||||
return input.substr(pos + 1);
|
||||
}
|
||||
}
|
||||
return input; // 如果没有找到分隔符,则返回整个字符串
|
||||
}
|
||||
|
||||
inline std::string get_env(std::string key, std::string default_value = ""){
|
||||
const char* value = std::getenv(key.c_str());
|
||||
inline std::string get_env(std::string key, std::string default_value = "")
|
||||
{
|
||||
const char *value = std::getenv(key.c_str());
|
||||
if (value) {
|
||||
return std::string(value);
|
||||
} else {
|
||||
|
@ -517,22 +496,25 @@ inline std::string get_env(std::string key, std::string default_value = ""){
|
|||
}
|
||||
}
|
||||
|
||||
inline std::string getCurrentTime() {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
inline std::string getCurrentTime()
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
|
||||
std::tm now_tm = *std::localtime(&now_c);
|
||||
std::tm now_tm = *std::localtime(&now_c);
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(&now_tm, "%Y-%m-%d %H:%M:%S");
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
inline std::string get_hostname() {
|
||||
inline std::string get_hostname()
|
||||
{
|
||||
char hostname[1024];
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
return std::string(hostname);
|
||||
}
|
||||
|
||||
inline std::string get_node_uuid(){
|
||||
inline std::string get_node_uuid()
|
||||
{
|
||||
std::hash<std::string> hasher;
|
||||
return std::to_string(hasher(get_hostname() + std::to_string(getpid())));
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ typedef struct main_opts {
|
|||
bool check;
|
||||
} main_opts;
|
||||
|
||||
|
||||
typedef struct export_opts {
|
||||
std::vector<std::string> file;
|
||||
std::vector<std::string> filelists;
|
||||
|
@ -38,10 +37,9 @@ typedef struct export_opts {
|
|||
std::string rname;
|
||||
} export_opts;
|
||||
|
||||
|
||||
typedef struct pack_opts {
|
||||
std::vector<std::string> files;
|
||||
std::vector<std::string> rename;
|
||||
std::vector<std::string> rename;
|
||||
bool example;
|
||||
bool force;
|
||||
} pack_opts;
|
||||
|
@ -66,9 +64,9 @@ typedef struct uvm_parameter {
|
|||
int is_marcro;
|
||||
std::string macro_name;
|
||||
std::string current_index;
|
||||
}uvm_parameter;
|
||||
} uvm_parameter;
|
||||
|
||||
typedef struct uvm_transaction_define{
|
||||
typedef struct uvm_transaction_define {
|
||||
std::string name;
|
||||
std::string filepath;
|
||||
std::string transaction_name;
|
||||
|
@ -76,5 +74,5 @@ typedef struct uvm_transaction_define{
|
|||
std::string data_now;
|
||||
std::vector<uvm_parameter> parameters;
|
||||
|
||||
}uvm_transaction_define;
|
||||
} uvm_transaction_define;
|
||||
} // namespace picker
|
||||
|
|
|
@ -3,14 +3,12 @@
|
|||
|
||||
namespace picker {
|
||||
|
||||
std::string replace_all(std::string str, const std::string &from,
|
||||
const std::string &to)
|
||||
std::string replace_all(std::string str, const std::string &from, const std::string &to)
|
||||
{
|
||||
size_t start_pos = 0;
|
||||
while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
||||
str.replace(start_pos, from.length(), to);
|
||||
start_pos +=
|
||||
to.length(); // Handles case where 'to' is a substring of 'from'
|
||||
start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
@ -18,8 +16,7 @@ std::string replace_all(std::string str, const std::string &from,
|
|||
namespace codegen {
|
||||
|
||||
namespace cxx {
|
||||
static const std::string xdata_declaration_template =
|
||||
" XData {{pin_uniq_name}};\n";
|
||||
static const std::string xdata_declaration_template = " XData {{pin_uniq_name}};\n";
|
||||
static const std::string xdata_reinit_template =
|
||||
" this->{{pin_uniq_name}}.ReInit({{logic_pin_length}}, IOType::{{logic_pin_type}}, \"{{logic_pin}}\");\n";
|
||||
static const std::string xdata_bindrw_template =
|
||||
|
@ -28,24 +25,20 @@ namespace codegen {
|
|||
" this->{{pin_uniq_name}}.BindDPIPtr(this->dut->GetDPIHandle((char *)\"{{pin_func_name}}\", 0), 0);\n";
|
||||
static const std::string xport_add_template =
|
||||
" this->xport.Add(this->{{pin_uniq_name}}.mName, this->{{pin_uniq_name}});\n";
|
||||
static const std::string comment_template =
|
||||
" {{logic_pin_type}} {{logic_pin_length}} {{logic_pin}}\n";
|
||||
static const std::string xport_cascaded_dec_template =
|
||||
" XPort {{port_name}};\n";
|
||||
static const std::string comment_template = " {{logic_pin_type}} {{logic_pin_length}} {{logic_pin}}\n";
|
||||
static const std::string xport_cascaded_dec_template = " XPort {{port_name}};\n";
|
||||
static const std::string xport_cascaded_sgn_template =
|
||||
" this->{{port_name}} = this->xport.NewSubPort(\"{{prefix_key}}_\");\n";
|
||||
|
||||
|
||||
#define BIND_DPI_RW \
|
||||
if (pin[i].logic_pin_hb == -1) { \
|
||||
data["logic_pin_length"] = 0; \
|
||||
data["read_func_type"] = "(void (*)(void*))"; \
|
||||
data["write_func_type"] = "(void (*)(const unsigned char))"; \
|
||||
} else { \
|
||||
data["logic_pin_length"] = \
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1; \
|
||||
data["read_func_type"] = "(void (*)(void*))"; \
|
||||
data["write_func_type"] = "(void (*)(const void*))"; \
|
||||
#define BIND_DPI_RW \
|
||||
if (pin[i].logic_pin_hb == -1) { \
|
||||
data["logic_pin_length"] = 0; \
|
||||
data["read_func_type"] = "(void (*)(void*))"; \
|
||||
data["write_func_type"] = "(void (*)(const unsigned char))"; \
|
||||
} else { \
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1; \
|
||||
data["read_func_type"] = "(void (*)(void*))"; \
|
||||
data["write_func_type"] = "(void (*)(const void*))"; \
|
||||
}
|
||||
|
||||
/// @brief Export external pin for cpp render
|
||||
|
@ -55,11 +48,9 @@ namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void render_external_pin(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &xdata_declaration,
|
||||
std::string &xdata_reinit,
|
||||
std::string &xdata_bindrw,
|
||||
std::string &xport_add, std::string &comments)
|
||||
void render_external_pin(std::vector<picker::sv_signal_define> pin, std::string &xdata_declaration,
|
||||
std::string &xdata_reinit, std::string &xdata_bindrw, std::string &xport_add,
|
||||
std::string &comments)
|
||||
{
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
|
@ -67,27 +58,22 @@ namespace codegen {
|
|||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
|
||||
// Set 0 for 1bit singal or hb-lb+1 for vector signal for cpp
|
||||
// render
|
||||
data["logic_pin_type"] = first_upercase(pin[i].logic_pin_type);
|
||||
|
||||
BIND_DPI_RW;
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
|
||||
xdata_declaration =
|
||||
xdata_declaration
|
||||
+ env.render(xdata_declaration_template, data);
|
||||
xdata_reinit =
|
||||
xdata_reinit + env.render(xdata_reinit_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_declaration = xdata_declaration + env.render(xdata_declaration_template, data);
|
||||
xdata_reinit = xdata_reinit + env.render(xdata_reinit_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,11 +84,8 @@ namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &xdata_declaration,
|
||||
std::string &xdata_reinit,
|
||||
std::string &xdata_bindrw,
|
||||
std::string &xport_add,
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin, std::string &xdata_declaration,
|
||||
std::string &xdata_reinit, std::string &xdata_bindrw, std::string &xport_add,
|
||||
std::string &comments)
|
||||
{
|
||||
inja::Environment env;
|
||||
|
@ -111,15 +94,13 @@ namespace codegen {
|
|||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
|
||||
// Set empty or [hb:lb] for verilog render
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ?
|
||||
"" :
|
||||
"[" + std::to_string(pin[i].logic_pin_hb) + ":"
|
||||
+ std::to_string(pin[i].logic_pin_lb) + "]";
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? "" :
|
||||
"[" + std::to_string(pin[i].logic_pin_hb) + ":"
|
||||
+ std::to_string(pin[i].logic_pin_lb) + "]";
|
||||
|
||||
comments = comments + env.render(comment_template, data);
|
||||
|
||||
|
@ -128,19 +109,16 @@ namespace codegen {
|
|||
BIND_DPI_RW;
|
||||
data["logic_pin_type"] = "Output";
|
||||
|
||||
xdata_declaration =
|
||||
xdata_declaration
|
||||
+ env.render(xdata_declaration_template, data);
|
||||
xdata_reinit =
|
||||
xdata_reinit + env.render(xdata_reinit_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bind_onlyr_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_declaration = xdata_declaration + env.render(xdata_declaration_template, data);
|
||||
xdata_reinit = xdata_reinit + env.render(xdata_reinit_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bind_onlyr_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
};
|
||||
|
||||
void render_cascaded_signals(std::string prefix, nlohmann::json &signal_tree_json,
|
||||
std::string &cascaded_ports_dec, std::string &cascaded_ports_sgn){
|
||||
std::string &cascaded_ports_dec, std::string &cascaded_ports_sgn)
|
||||
{
|
||||
nlohmann::json data;
|
||||
inja::Environment env;
|
||||
for (auto &[key, port] : signal_tree_json.items()) {
|
||||
|
@ -148,8 +126,8 @@ namespace codegen {
|
|||
continue;
|
||||
} else {
|
||||
std::string port_name = prefix.empty() ? key : prefix + "_" + key;
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
cascaded_ports_dec += env.render(xport_cascaded_dec_template, data);
|
||||
cascaded_ports_sgn += env.render(xport_cascaded_sgn_template, data);
|
||||
render_cascaded_signals(port_name, port, cascaded_ports_dec, cascaded_ports_sgn);
|
||||
|
@ -159,36 +137,31 @@ namespace codegen {
|
|||
|
||||
} // namespace cxx
|
||||
|
||||
void cpp(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
void cpp(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json)
|
||||
{
|
||||
//
|
||||
std::string src_dir = opts.source_dir + "/cpp";
|
||||
std::string dst_dir = opts.target_dir + "/cpp";
|
||||
std::string src_dir = opts.source_dir + "/cpp";
|
||||
std::string dst_dir = opts.target_dir + "/cpp";
|
||||
std::string dst_module_name = opts.target_module_name;
|
||||
|
||||
// Codegen Buffers
|
||||
std::string pin_connect, logic, wire, comments, dpi_export, dpi_impl,
|
||||
xdata_declaration, xdata_reinit, xdata_bindrw, xport_add, cascaded_signals_dec, cascaded_signals_sgn;
|
||||
std::string pin_connect, logic, wire, comments, dpi_export, dpi_impl, xdata_declaration, xdata_reinit,
|
||||
xdata_bindrw, xport_add, cascaded_signals_dec, cascaded_signals_sgn;
|
||||
|
||||
// Generate External Pin
|
||||
cxx::render_external_pin(external_pin, xdata_declaration, xdata_reinit,
|
||||
xdata_bindrw, xport_add, comments);
|
||||
cxx::render_external_pin(external_pin, xdata_declaration, xdata_reinit, xdata_bindrw, xport_add, comments);
|
||||
// Generate Internal Signal
|
||||
cxx::render_internal_signal(internal_signal, xdata_declaration,
|
||||
xdata_reinit, xdata_bindrw, xport_add,
|
||||
cxx::render_internal_signal(internal_signal, xdata_declaration, xdata_reinit, xdata_bindrw, xport_add,
|
||||
comments);
|
||||
// Generate Cascaded Ports
|
||||
cxx::render_cascaded_signals("", signal_tree_json, cascaded_signals_dec, cascaded_signals_sgn);
|
||||
|
||||
std::string erro_message;
|
||||
auto cpplib_location =
|
||||
picker::get_xcomm_lib("lib", erro_message);
|
||||
auto cpplib_location = picker::get_xcomm_lib("lib", erro_message);
|
||||
if (cpplib_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
|
||||
auto include_location =
|
||||
picker::get_xcomm_lib("include", erro_message);
|
||||
auto include_location = picker::get_xcomm_lib("include", erro_message);
|
||||
if (include_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
|
||||
// Set global render data
|
||||
|
@ -197,15 +170,15 @@ namespace codegen {
|
|||
data["__XSPCOMM_INCLUDE__"] = include_location;
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
|
||||
data["__XDATA_DECLARATION__"] = xdata_declaration;
|
||||
data["__XDATA_REINIT__"] = xdata_reinit;
|
||||
data["__XDATA_BIND__"] = xdata_bindrw;
|
||||
data["__XPORT_ADD__"] = xport_add;
|
||||
data["__XDATA_DECLARATION__"] = xdata_declaration;
|
||||
data["__XDATA_REINIT__"] = xdata_reinit;
|
||||
data["__XDATA_BIND__"] = xdata_bindrw;
|
||||
data["__XPORT_ADD__"] = xport_add;
|
||||
data["__XPORT_CASCADED_DEC__"] = cascaded_signals_dec;
|
||||
data["__XPORT_CASCADED_SGN__"] = cascaded_signals_sgn;
|
||||
|
||||
data["__COMMENTS__"] = comments;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
data["__COMMENTS__"] = comments;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
|
||||
// Render
|
||||
inja::Environment env;
|
||||
|
|
|
@ -4,16 +4,14 @@
|
|||
namespace picker { namespace codegen {
|
||||
|
||||
namespace go {
|
||||
static const std::string xdata_declare_template =
|
||||
" {{pin_uniq_name}} xspcomm.XData\n";
|
||||
static const std::string xdata_declare_template = " {{pin_uniq_name}} xspcomm.XData\n";
|
||||
static const std::string xdata_init_template =
|
||||
" self.{{pin_uniq_name}} = xspcomm.NewXData({{logic_pin_length}}, xspcomm.{{logic_pin_type}})\n";
|
||||
static const std::string xdata_bindrw_template =
|
||||
" self.{{pin_uniq_name}}.BindDPIPtr(self.Dut.GetDPIHandle(\"{{pin_func_name}}\", 0), self.Dut.GetDPIHandle(\"{{pin_func_name}}\", 1))\n";
|
||||
static const std::string xport_add_template =
|
||||
" self.Xport.Add(\"{{pin_func_name}}\", self.{{pin_uniq_name}})\n";
|
||||
static const std::string xport_cascaded_dec_template =
|
||||
" {{port_name}} xspcomm.XPort\n";
|
||||
static const std::string xport_cascaded_dec_template = " {{port_name}} xspcomm.XPort\n";
|
||||
static const std::string xport_cascaded_sgn_template =
|
||||
" self.{{port_name}} = self.Xport.NewSubPort(\"{{prefix_key}}_\")\n";
|
||||
|
||||
|
@ -24,35 +22,28 @@ namespace picker { namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void render_external_pin(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &xdata_decl,
|
||||
std::string &xdata_init,
|
||||
std::string &xdata_bindrw,
|
||||
std::string &xport_add,
|
||||
void render_external_pin(std::vector<picker::sv_signal_define> pin, std::string &xdata_decl,
|
||||
std::string &xdata_init, std::string &xdata_bindrw, std::string &xport_add,
|
||||
std::string &swig_constant)
|
||||
{
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] =
|
||||
(pin[i].logic_pin_type[0] == 'i') ? "IOType_Input" : "IOType_Output";
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, true);
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = (pin[i].logic_pin_type[0] == 'i') ? "IOType_Input" : "IOType_Output";
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, true);
|
||||
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
|
||||
xdata_decl =
|
||||
xdata_decl + env.render(xdata_declare_template, data);
|
||||
xdata_decl = xdata_decl + env.render(xdata_declare_template, data);
|
||||
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,11 +54,8 @@ namespace picker { namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &xdata_decl,
|
||||
std::string &xdata_init,
|
||||
std::string &xdata_bindrw,
|
||||
std::string &xport_add,
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin, std::string &xdata_decl,
|
||||
std::string &xdata_init, std::string &xdata_bindrw, std::string &xport_add,
|
||||
std::string &swig_constant)
|
||||
{
|
||||
inja::Environment env;
|
||||
|
@ -76,27 +64,25 @@ namespace picker { namespace codegen {
|
|||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, true);
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, true);
|
||||
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_type"] = "Out";
|
||||
|
||||
xdata_decl =
|
||||
xdata_decl + env.render(xdata_declare_template, data);
|
||||
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_decl = xdata_decl + env.render(xdata_declare_template, data);
|
||||
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
};
|
||||
|
||||
void render_cascaded_signals(std::string prefix, nlohmann::json &signal_tree_json,
|
||||
std::string &cascaded_ports_dec, std::string &cascaded_ports_sgn){
|
||||
std::string &cascaded_ports_dec, std::string &cascaded_ports_sgn)
|
||||
{
|
||||
nlohmann::json data;
|
||||
inja::Environment env;
|
||||
for (auto &[key, port] : signal_tree_json.items()) {
|
||||
|
@ -104,8 +90,8 @@ namespace picker { namespace codegen {
|
|||
continue;
|
||||
} else {
|
||||
std::string port_name = picker::capitalize_first_letter(prefix.empty() ? key : prefix + "_" + key);
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
cascaded_ports_dec += env.render(xport_cascaded_dec_template, data);
|
||||
cascaded_ports_sgn += env.render(xport_cascaded_sgn_template, data);
|
||||
render_cascaded_signals(port_name, port, cascaded_ports_dec, cascaded_ports_sgn);
|
||||
|
@ -113,11 +99,9 @@ namespace picker { namespace codegen {
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace go
|
||||
|
||||
} // namespace golang
|
||||
|
||||
void golang(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
void golang(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json)
|
||||
{
|
||||
//
|
||||
|
@ -127,14 +111,13 @@ namespace picker { namespace codegen {
|
|||
std::string simulator = opts.sim;
|
||||
|
||||
// Codegen Buffers
|
||||
std::string xdata_decl, xdata_init, xdata_bindrw, xport_add, swig_constant, cascaded_signals_dec, cascaded_signals_sgn;
|
||||
std::string xdata_decl, xdata_init, xdata_bindrw, xport_add, swig_constant, cascaded_signals_dec,
|
||||
cascaded_signals_sgn;
|
||||
|
||||
// Generate External Pin
|
||||
go::render_external_pin(external_pin, xdata_decl, xdata_init, xdata_bindrw,
|
||||
xport_add, swig_constant);
|
||||
go::render_external_pin(external_pin, xdata_decl, xdata_init, xdata_bindrw, xport_add, swig_constant);
|
||||
// Generate Internal Signal
|
||||
go::render_internal_signal(internal_signal, xdata_decl, xdata_init, xdata_bindrw,
|
||||
xport_add, swig_constant);
|
||||
go::render_internal_signal(internal_signal, xdata_decl, xdata_init, xdata_bindrw, xport_add, swig_constant);
|
||||
|
||||
// Generate Cascaded Ports
|
||||
go::render_cascaded_signals("", signal_tree_json, cascaded_signals_dec, cascaded_signals_sgn);
|
||||
|
@ -146,27 +129,25 @@ namespace picker { namespace codegen {
|
|||
nlohmann::json data;
|
||||
|
||||
std::string erro_message;
|
||||
auto golang_location =
|
||||
picker::get_xcomm_lib("golang", erro_message);
|
||||
auto golang_location = picker::get_xcomm_lib("golang", erro_message);
|
||||
if (golang_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
auto cpplib_location =
|
||||
picker::get_xcomm_lib("lib", erro_message);
|
||||
auto cpplib_location = picker::get_xcomm_lib("lib", erro_message);
|
||||
if (cpplib_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
|
||||
data["__XSPCOMM_LIB__"] = cpplib_location;
|
||||
data["__XSPCOMM_GOLANG__"] = golang_location;
|
||||
data["__XDATA_DECL__"] = xdata_decl;
|
||||
data["__TOP_MODULE_NAME__"]= dst_module_name;
|
||||
data["__XSPCOMM_LIB__"] = cpplib_location;
|
||||
data["__XSPCOMM_GOLANG__"] = golang_location;
|
||||
data["__XDATA_DECL__"] = xdata_decl;
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
|
||||
data["__XDATA_INIT__"] = xdata_init;
|
||||
data["__XDATA_BIND__"] = xdata_bindrw;
|
||||
data["__XPORT_ADD__"] = xport_add;
|
||||
data["__XDATA_INIT__"] = xdata_init;
|
||||
data["__XDATA_BIND__"] = xdata_bindrw;
|
||||
data["__XPORT_ADD__"] = xport_add;
|
||||
data["__XPORT_CASCADED_DEC__"] = cascaded_signals_dec;
|
||||
data["__XPORT_CASCADED_SGN__"] = cascaded_signals_sgn;
|
||||
|
||||
data["__SWIG_CONSTANT__"] = swig_constant;
|
||||
data["__USE_SIMULATOR__"] = "USE_" + simulator;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
data["__SWIG_CONSTANT__"] = swig_constant;
|
||||
data["__USE_SIMULATOR__"] = "USE_" + simulator;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
|
||||
// Render
|
||||
inja::Environment env;
|
||||
|
|
|
@ -4,16 +4,14 @@
|
|||
namespace picker { namespace codegen {
|
||||
|
||||
namespace java_ns {
|
||||
static const std::string xdata_declare_template =
|
||||
" public XData {{pin_uniq_name}};\n";
|
||||
static const std::string xdata_declare_template = " public XData {{pin_uniq_name}};\n";
|
||||
static const std::string xdata_init_template =
|
||||
" this.{{pin_uniq_name}} = new XData({{logic_pin_length}}, XData.{{logic_pin_type}});\n";
|
||||
static const std::string xdata_bindrw_template =
|
||||
" this.{{pin_uniq_name}}.BindDPIPtr(this.dut.GetDPIHandle(\"{{pin_func_name}}\", 0), this.dut.GetDPIHandle(\"{{pin_func_name}}\", 1));\n";
|
||||
static const std::string xport_add_template =
|
||||
" this.xport.Add(\"{{pin_func_name}}\", this.{{pin_uniq_name}});\n";
|
||||
static const std::string xport_cascaded_dec_template =
|
||||
" public XPort {{port_name}};\n";
|
||||
static const std::string xport_cascaded_dec_template = " public XPort {{port_name}};\n";
|
||||
static const std::string xport_cascaded_sgn_template =
|
||||
" this.{{port_name}} = this.xport.NewSubPort(\"{{prefix_key}}_\");\n";
|
||||
|
||||
|
@ -24,34 +22,28 @@ namespace picker { namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void
|
||||
render_external_pin(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &moudle_name, std::string &xdata_decl,
|
||||
std::string &xdata_init, std::string &xdata_bindrw,
|
||||
std::string &xport_add, std::string &swig_constant)
|
||||
void render_external_pin(std::vector<picker::sv_signal_define> pin, std::string &moudle_name,
|
||||
std::string &xdata_decl, std::string &xdata_init, std::string &xdata_bindrw,
|
||||
std::string &xport_add, std::string &swig_constant)
|
||||
{
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
data["moudle_name"] = moudle_name;
|
||||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] =
|
||||
(pin[i].logic_pin_type[0] == 'i') ? "In" : "Out";
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = (pin[i].logic_pin_type[0] == 'i') ? "In" : "Out";
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
|
||||
xdata_decl =
|
||||
xdata_decl + env.render(xdata_declare_template, data);
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_decl = xdata_decl + env.render(xdata_declare_template, data);
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,41 +54,35 @@ namespace picker { namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &moudle_name,
|
||||
std::string &xdata_decl,
|
||||
std::string &xdata_init,
|
||||
std::string &xdata_bindrw,
|
||||
std::string &xport_add,
|
||||
std::string &swig_constant)
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin, std::string &moudle_name,
|
||||
std::string &xdata_decl, std::string &xdata_init, std::string &xdata_bindrw,
|
||||
std::string &xport_add, std::string &swig_constant)
|
||||
{
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
data["moudle_name"] = moudle_name;
|
||||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_type"] = "Out";
|
||||
|
||||
xdata_decl =
|
||||
xdata_decl + env.render(xdata_declare_template, data);
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_decl = xdata_decl + env.render(xdata_declare_template, data);
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
};
|
||||
|
||||
void render_cascaded_signals(std::string prefix, nlohmann::json &signal_tree_json,
|
||||
std::string &cascaded_ports_dec, std::string &cascaded_ports_sgn){
|
||||
std::string &cascaded_ports_dec, std::string &cascaded_ports_sgn)
|
||||
{
|
||||
nlohmann::json data;
|
||||
inja::Environment env;
|
||||
for (auto &[key, port] : signal_tree_json.items()) {
|
||||
|
@ -104,8 +90,8 @@ namespace picker { namespace codegen {
|
|||
continue;
|
||||
} else {
|
||||
std::string port_name = prefix.empty() ? key : prefix + "_" + key;
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
cascaded_ports_dec += env.render(xport_cascaded_dec_template, data);
|
||||
cascaded_ports_sgn += env.render(xport_cascaded_sgn_template, data);
|
||||
render_cascaded_signals(port_name, port, cascaded_ports_dec, cascaded_ports_sgn);
|
||||
|
@ -115,8 +101,7 @@ namespace picker { namespace codegen {
|
|||
|
||||
} // namespace java_ns
|
||||
|
||||
void java(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
void java(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json)
|
||||
{
|
||||
std::string src_dir = opts.source_dir + "/java";
|
||||
|
@ -125,16 +110,14 @@ namespace picker { namespace codegen {
|
|||
std::string simulator = opts.sim;
|
||||
|
||||
// Codegen Buffers
|
||||
std::string xdata_decl, xdata_init, xdata_bindrw, xport_add,
|
||||
swig_constant, cascaded_signals_dec, cascaded_signals_sgn;
|
||||
std::string xdata_decl, xdata_init, xdata_bindrw, xport_add, swig_constant, cascaded_signals_dec,
|
||||
cascaded_signals_sgn;
|
||||
|
||||
// Generate External Pin
|
||||
java_ns::render_external_pin(external_pin, dst_module_name, xdata_decl,
|
||||
xdata_init, xdata_bindrw, xport_add,
|
||||
java_ns::render_external_pin(external_pin, dst_module_name, xdata_decl, xdata_init, xdata_bindrw, xport_add,
|
||||
swig_constant);
|
||||
// Generate Internal Signal
|
||||
java_ns::render_internal_signal(internal_signal, dst_module_name,
|
||||
xdata_decl, xdata_init, xdata_bindrw,
|
||||
java_ns::render_internal_signal(internal_signal, dst_module_name, xdata_decl, xdata_init, xdata_bindrw,
|
||||
xport_add, swig_constant);
|
||||
|
||||
// Generate Cascaded Ports
|
||||
|
@ -147,27 +130,25 @@ namespace picker { namespace codegen {
|
|||
nlohmann::json data;
|
||||
|
||||
std::string erro_message;
|
||||
auto java_location =
|
||||
picker::get_xcomm_lib("java/xspcomm-java.jar", erro_message);
|
||||
auto java_location = picker::get_xcomm_lib("java/xspcomm-java.jar", erro_message);
|
||||
if (java_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
auto cpplib_location =
|
||||
picker::get_xcomm_lib("lib", erro_message);
|
||||
auto cpplib_location = picker::get_xcomm_lib("lib", erro_message);
|
||||
if (cpplib_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
|
||||
data["__XSPCOMM_LIB__"] = cpplib_location;
|
||||
data["__XSPCOMM_JAR__"] = java_location;
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
data["__XSPCOMM_LIB__"] = cpplib_location;
|
||||
data["__XSPCOMM_JAR__"] = java_location;
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
|
||||
data["__XDATA_DECL__"] = xdata_decl;
|
||||
data["__XDATA_INIT__"] = xdata_init;
|
||||
data["__XDATA_BIND__"] = xdata_bindrw;
|
||||
data["__XPORT_ADD__"] = xport_add;
|
||||
data["__XDATA_DECL__"] = xdata_decl;
|
||||
data["__XDATA_INIT__"] = xdata_init;
|
||||
data["__XDATA_BIND__"] = xdata_bindrw;
|
||||
data["__XPORT_ADD__"] = xport_add;
|
||||
data["__XPORT_CASCADED_DEC__"] = cascaded_signals_dec;
|
||||
data["__XPORT_CASCADED_SGN__"] = cascaded_signals_sgn;
|
||||
|
||||
data["__SWIG_CONSTANT__"] = swig_constant;
|
||||
data["__USE_SIMULATOR__"] = "USE_" + simulator;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
data["__SWIG_CONSTANT__"] = swig_constant;
|
||||
data["__USE_SIMULATOR__"] = "USE_" + simulator;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
|
||||
// Render
|
||||
inja::Environment env;
|
||||
|
|
|
@ -11,10 +11,9 @@ namespace picker { namespace codegen {
|
|||
return false;
|
||||
}
|
||||
|
||||
void recursive_render(std::string &src_dir, std::string &dst_dir,
|
||||
nlohmann::json &data, inja::Environment &env)
|
||||
void recursive_render(std::string &src_dir, std::string &dst_dir, nlohmann::json &data, inja::Environment &env)
|
||||
{
|
||||
if(!std::filesystem::create_directories(dst_dir)){
|
||||
if (!std::filesystem::create_directories(dst_dir)) {
|
||||
PK_FATAL("Create: %s fail, please check if it is already exists", dst_dir.c_str());
|
||||
};
|
||||
// Render all files in src_dir to dst_dir
|
||||
|
@ -23,8 +22,7 @@ namespace picker { namespace codegen {
|
|||
std::string src_filename, dst_filename, dst_file_content;
|
||||
src_filename = entry.path().filename().string();
|
||||
dst_filename = dst_dir + "/" + src_filename;
|
||||
PK_MESSAGE("Render file: %s to %s", src_filename.c_str(),
|
||||
dst_filename.c_str());
|
||||
PK_MESSAGE("Render file: %s to %s", src_filename.c_str(), dst_filename.c_str());
|
||||
dst_file_content = env.render_file(entry.path().string(), data);
|
||||
write_file(dst_filename, dst_file_content);
|
||||
} else if (entry.is_directory()) {
|
||||
|
@ -36,13 +34,13 @@ namespace picker { namespace codegen {
|
|||
}
|
||||
}
|
||||
|
||||
void gen_filelist(const std::vector<std::string> &source_file,
|
||||
const std::vector<std::string> &ifilelists, std::string &ofilelist)
|
||||
void gen_filelist(const std::vector<std::string> &source_file, const std::vector<std::string> &ifilelists,
|
||||
std::string &ofilelist)
|
||||
{
|
||||
std::vector<std::string> path_list;
|
||||
const std::vector<std::string> allow_file_types = {".sv", ".v", ".cpp", ".c", ".cc", ".cxx", ".so", ".a", ".o"};
|
||||
std::string fs_path = "";
|
||||
for (auto ifilelist: ifilelists) {
|
||||
std::string fs_path = "";
|
||||
for (auto ifilelist : ifilelists) {
|
||||
if (check_file_type(ifilelist, {".txt", ".f"})) { // file
|
||||
std::ifstream ifs(ifilelist);
|
||||
std::string line;
|
||||
|
@ -56,34 +54,32 @@ namespace picker { namespace codegen {
|
|||
}
|
||||
for (auto &path : path_list) {
|
||||
path = picker::trim(path);
|
||||
if (path.starts_with("#")) { continue; } // skip comment line
|
||||
if (path.starts_with("#")) { continue; } // skip comment line
|
||||
path = picker::trim(path.substr(0, path.find_first_of("#"))); // remove comment part
|
||||
if (path.empty()) { continue; } // skip empty line
|
||||
if (picker::contians(source_file, path)) { continue; } // skip source file
|
||||
if (path.empty()) { continue; } // skip empty line
|
||||
if (picker::contians(source_file, path)) { continue; } // skip source file
|
||||
|
||||
if (check_file_type(path, allow_file_types)) { // file
|
||||
auto target_file = path;
|
||||
if(!std::filesystem::exists(path) && !path.starts_with("/") && !fs_path.empty()) {
|
||||
if (!std::filesystem::exists(path) && !path.starts_with("/") && !fs_path.empty()) {
|
||||
PK_ERROR("Cannot find file: %s, try search in path: %s", path.c_str(), fs_path.c_str());
|
||||
path = (std::filesystem::path(fs_path)/path).string();
|
||||
path = (std::filesystem::path(fs_path) / path).string();
|
||||
}
|
||||
if (!std::filesystem::exists(path))PK_FATAL("File not found: %s\n", target_file.c_str());
|
||||
if (!std::filesystem::exists(path)) PK_FATAL("File not found: %s\n", target_file.c_str());
|
||||
path = std::filesystem::absolute(path).string();
|
||||
ofilelist += path + "\n";
|
||||
} else if (path.ends_with("/")) { // directory
|
||||
auto target_dir = path;
|
||||
if(!std::filesystem::exists(path) && !path.starts_with("/") && !fs_path.empty()) {
|
||||
if (!std::filesystem::exists(path) && !path.starts_with("/") && !fs_path.empty()) {
|
||||
PK_ERROR("Cannot find directory: %s, try search in path: %s", path.c_str(), fs_path.c_str());
|
||||
path = (std::filesystem::path(fs_path)/path).string();
|
||||
path = (std::filesystem::path(fs_path) / path).string();
|
||||
}
|
||||
if (!std::filesystem::exists(path))PK_FATAL("Directory not found: %s\n", target_dir.c_str());
|
||||
if (!std::filesystem::exists(path)) PK_FATAL("Directory not found: %s\n", target_dir.c_str());
|
||||
std::filesystem::recursive_directory_iterator iter(path);
|
||||
for (const auto &entry : iter) {
|
||||
if (entry.is_regular_file()) {
|
||||
std::string filename = entry.path().filename().string();
|
||||
if (check_file_type(filename, allow_file_types)) {
|
||||
ofilelist += entry.path().string() + "\n";
|
||||
}
|
||||
if (check_file_type(filename, allow_file_types)) { ofilelist += entry.path().string() + "\n"; }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -92,8 +88,7 @@ namespace picker { namespace codegen {
|
|||
}
|
||||
}
|
||||
|
||||
void get_clock_period(std::string &vcs_clock_period_h,
|
||||
std::string &vcs_clock_period_l,
|
||||
void get_clock_period(std::string &vcs_clock_period_h, std::string &vcs_clock_period_l,
|
||||
const std::string &frequency)
|
||||
{
|
||||
// h,l with ps unit
|
||||
|
@ -117,10 +112,8 @@ namespace picker { namespace codegen {
|
|||
vcs_clock_period_l = std::to_string(period >> 1);
|
||||
}
|
||||
|
||||
void gen_cmake(std::string &src_dir, std::string &dst_dir,
|
||||
std::string &wave_file_name, std::string &simulator,
|
||||
std::string &vflag, std::string &cflag,
|
||||
inja::Environment &env, nlohmann::json &data)
|
||||
void gen_cmake(std::string &src_dir, std::string &dst_dir, std::string &wave_file_name, std::string &simulator,
|
||||
std::string &vflag, std::string &cflag, inja::Environment &env, nlohmann::json &data)
|
||||
{
|
||||
data["__SIMULATOR__"] = simulator;
|
||||
data["__VFLAG__"] = vflag;
|
||||
|
@ -130,37 +123,31 @@ namespace picker { namespace codegen {
|
|||
}
|
||||
|
||||
std::vector<picker::sv_signal_define> lib(picker::export_opts &opts,
|
||||
const std::vector<picker::sv_module_define> sv_module_result,
|
||||
const std::vector<picker::sv_signal_define> &internal_pin,
|
||||
nlohmann::json &signal_tree)
|
||||
const std::vector<picker::sv_module_define> sv_module_result,
|
||||
const std::vector<picker::sv_signal_define> &internal_pin,
|
||||
nlohmann::json &signal_tree)
|
||||
{
|
||||
std::vector<picker::sv_signal_define> ret;
|
||||
// Parse Options
|
||||
std::string src_dir = opts.source_dir + "/lib",
|
||||
dst_dir = opts.target_dir,
|
||||
dst_module_name = opts.target_module_name,
|
||||
wave_file_name = opts.wave_file_name, simulator = opts.sim,
|
||||
vflag = opts.vflag, cflag = opts.cflag,
|
||||
ofilelist, vcs_clock_period_h,
|
||||
std::string src_dir = opts.source_dir + "/lib", dst_dir = opts.target_dir,
|
||||
dst_module_name = opts.target_module_name, wave_file_name = opts.wave_file_name,
|
||||
simulator = opts.sim, vflag = opts.vflag, cflag = opts.cflag, ofilelist, vcs_clock_period_h,
|
||||
vcs_clock_period_l;
|
||||
std::vector<std::string> files = opts.file;
|
||||
std::vector<std::string> files = opts.file;
|
||||
std::vector<std::string> ifilelists = opts.filelists;
|
||||
|
||||
// Build environment
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
|
||||
ret = gen_sv_param(data, sv_module_result, internal_pin, signal_tree,
|
||||
wave_file_name, simulator);
|
||||
gen_cmake(src_dir, dst_dir, wave_file_name, simulator, vflag, cflag,
|
||||
env, data);
|
||||
ret = gen_sv_param(data, sv_module_result, internal_pin, signal_tree, wave_file_name, simulator);
|
||||
gen_cmake(src_dir, dst_dir, wave_file_name, simulator, vflag, cflag, env, data);
|
||||
|
||||
// Set clock period
|
||||
printf("Frequency: %s\n", opts.frequency.c_str());
|
||||
get_clock_period(vcs_clock_period_h, vcs_clock_period_l,
|
||||
opts.frequency);
|
||||
get_clock_period(vcs_clock_period_h, vcs_clock_period_l, opts.frequency);
|
||||
|
||||
// Render lib filelist
|
||||
gen_filelist(files, ifilelists, ofilelist);
|
||||
|
@ -182,20 +169,16 @@ namespace picker { namespace codegen {
|
|||
if (entry.is_regular_file()) {
|
||||
std::string src_filename, dst_filename;
|
||||
src_filename = entry.path().filename().string();
|
||||
if (src_filename.ends_with(".sv")
|
||||
|| src_filename.ends_with(".v")) {
|
||||
std::filesystem::rename(
|
||||
entry.path(),
|
||||
entry.path().parent_path()
|
||||
/ (dst_module_name + "_"
|
||||
+ entry.path().filename().string()));
|
||||
if (src_filename.ends_with(".sv") || src_filename.ends_with(".v")) {
|
||||
std::filesystem::rename(entry.path(),
|
||||
entry.path().parent_path()
|
||||
/ (dst_module_name + "_" + entry.path().filename().string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
for(auto &f: files){
|
||||
std::filesystem::copy_file(
|
||||
f, dst_dir + "/" + dst_module_name + ".v",
|
||||
std::filesystem::copy_options::overwrite_existing);
|
||||
for (auto &f : files) {
|
||||
std::filesystem::copy_file(f, dst_dir + "/" + dst_module_name + ".v",
|
||||
std::filesystem::copy_options::overwrite_existing);
|
||||
}
|
||||
PK_MESSAGE("Generate DPI files successfully!");
|
||||
return ret;
|
||||
|
|
|
@ -20,31 +20,25 @@ namespace picker { namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void render_external_pin(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &xdata_init,
|
||||
std::string &xdata_bindrw,
|
||||
std::string &xport_add,
|
||||
std::string &swig_constant)
|
||||
void render_external_pin(std::vector<picker::sv_signal_define> pin, std::string &xdata_init,
|
||||
std::string &xdata_bindrw, std::string &xport_add, std::string &swig_constant)
|
||||
{
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] =
|
||||
(pin[i].logic_pin_type[0] == 'i') ? "In" : "Out";
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = (pin[i].logic_pin_type[0] == 'i') ? "In" : "Out";
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,11 +49,8 @@ namespace picker { namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &xdata_init,
|
||||
std::string &xdata_bindrw,
|
||||
std::string &xport_add,
|
||||
std::string &swig_constant)
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin, std::string &xdata_init,
|
||||
std::string &xdata_bindrw, std::string &xport_add, std::string &swig_constant)
|
||||
{
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
|
@ -67,23 +58,22 @@ namespace picker { namespace codegen {
|
|||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_type"] = "Out";
|
||||
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
};
|
||||
|
||||
void render_cascaded_signals(std::string prefix, nlohmann::json &signal_tree_json, std::string &cascaded_ports){
|
||||
void render_cascaded_signals(std::string prefix, nlohmann::json &signal_tree_json, std::string &cascaded_ports)
|
||||
{
|
||||
nlohmann::json data;
|
||||
inja::Environment env;
|
||||
for (auto &[key, port] : signal_tree_json.items()) {
|
||||
|
@ -91,8 +81,8 @@ namespace picker { namespace codegen {
|
|||
continue;
|
||||
} else {
|
||||
std::string port_name = prefix.empty() ? key : prefix + "_" + key;
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
cascaded_ports += env.render(xport_cascaded_template, data);
|
||||
render_cascaded_signals(port_name, port, cascaded_ports);
|
||||
}
|
||||
|
@ -101,8 +91,7 @@ namespace picker { namespace codegen {
|
|||
|
||||
} // namespace py
|
||||
|
||||
void python(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
void python(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json)
|
||||
{
|
||||
//
|
||||
|
@ -115,11 +104,9 @@ namespace picker { namespace codegen {
|
|||
std::string xdata_init, xdata_bindrw, xport_add, swig_constant, cascaded_signals;
|
||||
|
||||
// Generate External Pin
|
||||
py::render_external_pin(external_pin, xdata_init, xdata_bindrw,
|
||||
xport_add, swig_constant);
|
||||
py::render_external_pin(external_pin, xdata_init, xdata_bindrw, xport_add, swig_constant);
|
||||
// Generate Internal Signal
|
||||
py::render_internal_signal(internal_signal, xdata_init, xdata_bindrw,
|
||||
xport_add, swig_constant);
|
||||
py::render_internal_signal(internal_signal, xdata_init, xdata_bindrw, xport_add, swig_constant);
|
||||
// Generate Cascaded Porst
|
||||
py::render_cascaded_signals("", signal_tree_json, cascaded_signals);
|
||||
|
||||
|
@ -130,25 +117,23 @@ namespace picker { namespace codegen {
|
|||
nlohmann::json data;
|
||||
|
||||
std::string erro_message;
|
||||
auto python_location =
|
||||
picker::get_xcomm_lib("python/xspcomm", erro_message);
|
||||
auto python_location = picker::get_xcomm_lib("python/xspcomm", erro_message);
|
||||
if (python_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
auto cpplib_location =
|
||||
picker::get_xcomm_lib("lib", erro_message);
|
||||
auto cpplib_location = picker::get_xcomm_lib("lib", erro_message);
|
||||
if (cpplib_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
|
||||
data["__XSPCOMM_LIB__"] = cpplib_location;
|
||||
data["__XSPCOMM_PYTHON__"] = python_location;
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
data["__XSPCOMM_LIB__"] = cpplib_location;
|
||||
data["__XSPCOMM_PYTHON__"] = python_location;
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
|
||||
data["__XDATA_INIT__"] = xdata_init;
|
||||
data["__XDATA_BIND__"] = xdata_bindrw;
|
||||
data["__XPORT_ADD__"] = xport_add;
|
||||
data["__XPORT_CASCADED__"] = cascaded_signals;
|
||||
|
||||
data["__SWIG_CONSTANT__"] = swig_constant;
|
||||
data["__USE_SIMULATOR__"] = "USE_" + simulator;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
data["__SWIG_CONSTANT__"] = swig_constant;
|
||||
data["__USE_SIMULATOR__"] = "USE_" + simulator;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
|
||||
// Render
|
||||
inja::Environment env;
|
||||
|
|
|
@ -20,32 +20,27 @@ namespace picker { namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void
|
||||
render_external_pin(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &moudle_name,
|
||||
std::string &xdata_init, std::string &xdata_bindrw,
|
||||
std::string &xport_add, std::string &swig_constant)
|
||||
void render_external_pin(std::vector<picker::sv_signal_define> pin, std::string &moudle_name,
|
||||
std::string &xdata_init, std::string &xdata_bindrw, std::string &xport_add,
|
||||
std::string &swig_constant)
|
||||
{
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
data["moudle_name"] = moudle_name;
|
||||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] =
|
||||
(pin[i].logic_pin_type[0] == 'i') ? "In" : "Out";
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = (pin[i].logic_pin_type[0] == 'i') ? "In" : "Out";
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,37 +51,33 @@ namespace picker { namespace codegen {
|
|||
/// @param xdata_bindrw
|
||||
/// @param xport_add
|
||||
/// @param comments
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &moudle_name,
|
||||
std::string &xdata_init,
|
||||
std::string &xdata_bindrw,
|
||||
std::string &xport_add,
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin, std::string &moudle_name,
|
||||
std::string &xdata_init, std::string &xdata_bindrw, std::string &xport_add,
|
||||
std::string &swig_constant)
|
||||
{
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
auto pin_map = picker::get_default_confilct_map();
|
||||
data["moudle_name"] = moudle_name;
|
||||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["pin_uniq_name"] = picker::fix_conflict_pin_name(data["pin_func_name"], pin_map, false);
|
||||
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? // means not vector
|
||||
0 :
|
||||
pin[i].logic_pin_hb - pin[i].logic_pin_lb + 1;
|
||||
data["logic_pin_type"] = "Out";
|
||||
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw =
|
||||
xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
xdata_init = xdata_init + env.render(xdata_init_template, data);
|
||||
xdata_bindrw = xdata_bindrw + env.render(xdata_bindrw_template, data);
|
||||
xport_add = xport_add + env.render(xport_add_template, data);
|
||||
}
|
||||
};
|
||||
|
||||
void render_cascaded_signals(std::string prefix, nlohmann::json &signal_tree_json, std::string &cascaded_ports){
|
||||
void render_cascaded_signals(std::string prefix, nlohmann::json &signal_tree_json, std::string &cascaded_ports)
|
||||
{
|
||||
nlohmann::json data;
|
||||
inja::Environment env;
|
||||
for (auto &[key, port] : signal_tree_json.items()) {
|
||||
|
@ -94,8 +85,8 @@ namespace picker { namespace codegen {
|
|||
continue;
|
||||
} else {
|
||||
std::string port_name = prefix.empty() ? key : prefix + "_" + key;
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
data["port_name"] = port_name;
|
||||
data["prefix_key"] = port_name;
|
||||
cascaded_ports += env.render(xport_cascaded_sgn_template, data);
|
||||
render_cascaded_signals(port_name, port, cascaded_ports);
|
||||
}
|
||||
|
@ -104,9 +95,8 @@ namespace picker { namespace codegen {
|
|||
|
||||
} // namespace scala_ns
|
||||
|
||||
void scala(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json)
|
||||
void scala(picker::export_opts &opts, std::vector<picker::sv_signal_define> external_pin,
|
||||
std::vector<picker::sv_signal_define> internal_signal, nlohmann::json &signal_tree_json)
|
||||
{
|
||||
std::string src_dir = opts.source_dir + "/scala";
|
||||
std::string dst_dir = opts.target_dir + "/scala";
|
||||
|
@ -114,17 +104,14 @@ namespace picker { namespace codegen {
|
|||
std::string simulator = opts.sim;
|
||||
|
||||
// Codegen Buffers
|
||||
std::string xdata_init, xdata_bindrw, xport_add,
|
||||
swig_constant, cascaded_signals_sgn;
|
||||
std::string xdata_init, xdata_bindrw, xport_add, swig_constant, cascaded_signals_sgn;
|
||||
|
||||
// Generate External Pin
|
||||
scala_ns::render_external_pin(external_pin, dst_module_name,
|
||||
xdata_init, xdata_bindrw, xport_add,
|
||||
swig_constant);
|
||||
scala_ns::render_external_pin(external_pin, dst_module_name, xdata_init, xdata_bindrw, xport_add,
|
||||
swig_constant);
|
||||
// Generate Internal Signal
|
||||
scala_ns::render_internal_signal(internal_signal, dst_module_name,
|
||||
xdata_init, xdata_bindrw,
|
||||
xport_add, swig_constant);
|
||||
scala_ns::render_internal_signal(internal_signal, dst_module_name, xdata_init, xdata_bindrw, xport_add,
|
||||
swig_constant);
|
||||
// Generate Cascaded Porst
|
||||
scala_ns::render_cascaded_signals("", signal_tree_json, cascaded_signals_sgn);
|
||||
|
||||
|
@ -135,25 +122,23 @@ namespace picker { namespace codegen {
|
|||
nlohmann::json data;
|
||||
|
||||
std::string erro_message;
|
||||
auto scala_location =
|
||||
picker::get_xcomm_lib("scala/xspcomm-scala.jar", erro_message);
|
||||
auto scala_location = picker::get_xcomm_lib("scala/xspcomm-scala.jar", erro_message);
|
||||
if (scala_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
auto cpplib_location =
|
||||
picker::get_xcomm_lib("lib", erro_message);
|
||||
auto cpplib_location = picker::get_xcomm_lib("lib", erro_message);
|
||||
if (cpplib_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
|
||||
data["__XSPCOMM_LIB__"] = cpplib_location;
|
||||
data["__XSPCOMM_JAR__"] = scala_location;
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
data["__XSPCOMM_LIB__"] = cpplib_location;
|
||||
data["__XSPCOMM_JAR__"] = scala_location;
|
||||
data["__TOP_MODULE_NAME__"] = dst_module_name;
|
||||
|
||||
data["__XDATA_INIT__"] = xdata_init;
|
||||
data["__XDATA_BIND__"] = xdata_bindrw;
|
||||
data["__XPORT_ADD__"] = xport_add;
|
||||
data["__XDATA_INIT__"] = xdata_init;
|
||||
data["__XDATA_BIND__"] = xdata_bindrw;
|
||||
data["__XPORT_ADD__"] = xport_add;
|
||||
data["__XPORT_CASCADED_SGN__"] = cascaded_signals_sgn;
|
||||
|
||||
data["__SWIG_CONSTANT__"] = swig_constant;
|
||||
data["__USE_SIMULATOR__"] = "USE_" + simulator;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
data["__SWIG_CONSTANT__"] = swig_constant;
|
||||
data["__USE_SIMULATOR__"] = "USE_" + simulator;
|
||||
data["__COPY_XSPCOMM_LIB__"] = opts.cp_lib;
|
||||
|
||||
// Render
|
||||
inja::Environment env;
|
||||
|
|
|
@ -6,12 +6,9 @@ namespace picker { namespace codegen {
|
|||
namespace sv {
|
||||
static const std::string sub_module_template =
|
||||
" {{module_name}} {{module_name}}{{module_subfix}}(\n{{pin_connect}}\n );\n";
|
||||
static const std::string pin_connect_template =
|
||||
" .{{raw_pin}}({{logic_pin}}),\n";
|
||||
static const std::string logic_pin_declaration_template =
|
||||
" logic {{logic_pin_length}} {{logic_pin}};\n";
|
||||
static const std::string wire_pin_declaration_template =
|
||||
" wire {{logic_pin_length}} {{logic_pin}};\n";
|
||||
static const std::string pin_connect_template = " .{{raw_pin}}({{logic_pin}}),\n";
|
||||
static const std::string logic_pin_declaration_template = " logic {{logic_pin_length}} {{logic_pin}};\n";
|
||||
static const std::string wire_pin_declaration_template = " wire {{logic_pin_length}} {{logic_pin}};\n";
|
||||
|
||||
static const std::string dpi_get_export_template =
|
||||
" export \"DPI-C\" function get_{{pin_func_name}}xx{{__LIB_DPI_FUNC_NAME_HASH__}};\n";
|
||||
|
@ -43,53 +40,52 @@ namespace picker { namespace codegen {
|
|||
/// @param wire
|
||||
/// @param dpi_export
|
||||
/// @param dpi_impl
|
||||
std::vector<picker::sv_signal_define> render_external_pin(std::vector<picker::sv_module_define> sv_module_result,
|
||||
std::string &inner_modules, std::string &logic,
|
||||
std::string &wire, std::string &dpi_export,
|
||||
std::string &dpi_impl)
|
||||
std::vector<picker::sv_signal_define>
|
||||
render_external_pin(std::vector<picker::sv_module_define> sv_module_result, std::string &inner_modules,
|
||||
std::string &logic, std::string &wire, std::string &dpi_export, std::string &dpi_impl)
|
||||
{
|
||||
std::vector<picker::sv_signal_define> ret;
|
||||
inja::Environment env;
|
||||
auto module_diffs = sv_module_result.size();
|
||||
for(int diff_index=0; diff_index < module_diffs; diff_index++){
|
||||
for (int diff_index = 0; diff_index < module_diffs; diff_index++) {
|
||||
auto &module = sv_module_result[diff_index];
|
||||
PK_DEBUG("module_name: %s, module_nums: %d", module.module_name.c_str(), module.module_nums);
|
||||
for(int count_index=0; count_index < module.module_nums; count_index++){
|
||||
for (int count_index = 0; count_index < module.module_nums; count_index++) {
|
||||
nlohmann::json data;
|
||||
std::string pin_connect, pin_prefix;
|
||||
auto &pin = module.pins;
|
||||
if(module_diffs != 1 || module.module_nums != 1) pin_prefix = module.module_name + "_";
|
||||
if(module.module_nums != 1) {
|
||||
if (module_diffs != 1 || module.module_nums != 1) pin_prefix = module.module_name + "_";
|
||||
if (module.module_nums != 1) {
|
||||
pin_prefix += std::to_string(count_index) + "_";
|
||||
data["module_subfix"] = "_" + std::to_string(count_index);
|
||||
} else data["module_subfix"] = "";
|
||||
} else
|
||||
data["module_subfix"] = "";
|
||||
data["module_name"] = module.module_name;
|
||||
PK_DEBUG("module_subfix: %s, pin_prefix: %s", data["module_subfix"].dump().c_str(), pin_prefix.c_str());
|
||||
PK_DEBUG("module_subfix: %s, pin_prefix: %s", data["module_subfix"].dump().c_str(),
|
||||
pin_prefix.c_str());
|
||||
for (int i = 0; i < pin.size(); i++) {
|
||||
picker::sv_signal_define temp_pin = pin[i];
|
||||
temp_pin.logic_pin = pin_prefix + pin[i].logic_pin;
|
||||
ret.push_back(temp_pin); // pins need export
|
||||
data["raw_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin"] = temp_pin.logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(temp_pin.logic_pin, ".", "_");
|
||||
temp_pin.logic_pin = pin_prefix + pin[i].logic_pin;
|
||||
ret.push_back(temp_pin); // pins need export
|
||||
data["raw_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin"] = temp_pin.logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(temp_pin.logic_pin, ".", "_");
|
||||
data["__LIB_DPI_FUNC_NAME_HASH__"] = std::string(lib_random_hash);
|
||||
// Set empty or [hb:lb] for verilog render
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ?
|
||||
"" :
|
||||
"[" + std::to_string(pin[i].logic_pin_hb) + ":"
|
||||
+ std::to_string(pin[i].logic_pin_lb) + "]";
|
||||
pin_connect =
|
||||
pin_connect + env.render(pin_connect_template, data);
|
||||
logic =
|
||||
logic + env.render(logic_pin_declaration_template, data);
|
||||
wire = wire + env.render(wire_pin_declaration_template, data);
|
||||
dpi_export = dpi_export
|
||||
+ env.render(dpi_get_export_template, data)
|
||||
+ env.render(dpi_set_export_template, data);
|
||||
dpi_impl = dpi_impl + env.render(dpi_get_impl_template, data)
|
||||
+ env.render(dpi_set_impl_template, data);
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ?
|
||||
"" :
|
||||
"[" + std::to_string(pin[i].logic_pin_hb) + ":"
|
||||
+ std::to_string(pin[i].logic_pin_lb) + "]";
|
||||
pin_connect += env.render(pin_connect_template, data);
|
||||
logic += env.render(logic_pin_declaration_template, data);
|
||||
wire += env.render(wire_pin_declaration_template, data);
|
||||
dpi_export += env.render(dpi_get_export_template, data);
|
||||
dpi_impl += env.render(dpi_get_impl_template, data);
|
||||
if (pin[i].logic_pin_type != "output") {
|
||||
dpi_export += env.render(dpi_set_export_template, data);
|
||||
dpi_impl += env.render(dpi_set_impl_template, data);
|
||||
}
|
||||
}
|
||||
if (pin_connect.length() == 0)
|
||||
PK_FATAL(
|
||||
|
@ -109,86 +105,73 @@ namespace picker { namespace codegen {
|
|||
/// @param pin
|
||||
/// @param dpi_export
|
||||
/// @param dpi_impl
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin,
|
||||
std::string &dpi_export,
|
||||
void render_internal_signal(std::vector<picker::sv_signal_define> pin, std::string &dpi_export,
|
||||
std::string &dpi_impl)
|
||||
{
|
||||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
for (int i = 0; i < pin.size(); i++) {
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["__LIB_DPI_FUNC_NAME_HASH__"] =
|
||||
std::string(lib_random_hash);
|
||||
data["logic_pin"] = pin[i].logic_pin;
|
||||
data["logic_pin_type"] = pin[i].logic_pin_type;
|
||||
data["pin_func_name"] = replace_all(pin[i].logic_pin, ".", "_");
|
||||
data["__LIB_DPI_FUNC_NAME_HASH__"] = std::string(lib_random_hash);
|
||||
|
||||
// Set empty or [hb:lb] for verilog render
|
||||
data["logic_pin_length"] =
|
||||
pin[i].logic_pin_hb == -1 ?
|
||||
"" :
|
||||
"[" + std::to_string(pin[i].logic_pin_hb) + ":"
|
||||
+ std::to_string(pin[i].logic_pin_lb) + "]";
|
||||
data["logic_pin_length"] = pin[i].logic_pin_hb == -1 ? "" :
|
||||
"[" + std::to_string(pin[i].logic_pin_hb) + ":"
|
||||
+ std::to_string(pin[i].logic_pin_lb) + "]";
|
||||
|
||||
dpi_export =
|
||||
dpi_export + env.render(dpi_get_export_template, data);
|
||||
dpi_impl = dpi_impl + env.render(dpi_get_impl_template, data);
|
||||
dpi_export = dpi_export + env.render(dpi_get_export_template, data);
|
||||
dpi_impl = dpi_impl + env.render(dpi_get_impl_template, data);
|
||||
}
|
||||
};
|
||||
|
||||
void render_sv_waveform(const std::string &simulator,
|
||||
const std::string &wave_file_name,
|
||||
nlohmann::json &data)
|
||||
void render_sv_waveform(const std::string &simulator, const std::string &wave_file_name, nlohmann::json &data)
|
||||
{
|
||||
inja::Environment env;
|
||||
std::string sv_dump_wave, trace, dum_var_options;
|
||||
dum_var_options = picker::get_env("DUMPVARS_OPTION", "");
|
||||
if(!dum_var_options.empty()){
|
||||
if (!dum_var_options.empty()) {
|
||||
PK_DEBUG("Find DUMPVARS_OPTION=%s", dum_var_options.c_str());
|
||||
dum_var_options = ", \""+dum_var_options + "\"";
|
||||
dum_var_options = ", \"" + dum_var_options + "\"";
|
||||
}
|
||||
data["__WAVE_FILE_NAME__"] = wave_file_name;
|
||||
data["__WAVE_FILE_NAME__"] = wave_file_name;
|
||||
data["__DUMP_VAR_OPTIONS__"] = dum_var_options;
|
||||
if (simulator == "verilator") {
|
||||
if (wave_file_name.length() > 0) {
|
||||
if (wave_file_name.ends_with(".vcd")
|
||||
|| wave_file_name.ends_with(".fst"))
|
||||
sv_dump_wave = env.render(
|
||||
" initial begin\n"
|
||||
" $dumpfile(\"{{__WAVE_FILE_NAME__}}\");\n"
|
||||
" $dumpvars(0, {{__TOP_MODULE_NAME__}}_top{{__DUMP_VAR_OPTIONS__}});\n"
|
||||
" end",
|
||||
data);
|
||||
if (wave_file_name.ends_with(".vcd") || wave_file_name.ends_with(".fst"))
|
||||
sv_dump_wave =
|
||||
env.render(" initial begin\n"
|
||||
" $dumpfile(\"{{__WAVE_FILE_NAME__}}\");\n"
|
||||
" $dumpvars(0, {{__TOP_MODULE_NAME__}}_top{{__DUMP_VAR_OPTIONS__}});\n"
|
||||
" end",
|
||||
data);
|
||||
else
|
||||
PK_FATAL(
|
||||
"Verilator trace file must be .vcd or .fst format.\n");
|
||||
PK_FATAL("Verilator trace file must be .vcd or .fst format.\n");
|
||||
}
|
||||
} else if (simulator == "vcs") {
|
||||
if (wave_file_name.length() > 0) {
|
||||
if (wave_file_name.ends_with(".fsdb") == false)
|
||||
PK_FATAL("VCS trace file must be .fsdb format.\n");
|
||||
sv_dump_wave = env.render(
|
||||
" initial begin\n"
|
||||
" $fsdbDumpfile(\"{{__WAVE_FILE_NAME__}}\");\n"
|
||||
" $fsdbDumpvars(0, {{__TOP_MODULE_NAME__}}_top{{__DUMP_VAR_OPTIONS__}});\n"
|
||||
" end",
|
||||
data);
|
||||
if (wave_file_name.ends_with(".fsdb") == false) PK_FATAL("VCS trace file must be .fsdb format.\n");
|
||||
sv_dump_wave =
|
||||
env.render(" initial begin\n"
|
||||
" $fsdbDumpfile(\"{{__WAVE_FILE_NAME__}}\");\n"
|
||||
" $fsdbDumpvars(0, {{__TOP_MODULE_NAME__}}_top{{__DUMP_VAR_OPTIONS__}});\n"
|
||||
" end",
|
||||
data);
|
||||
}
|
||||
} else {
|
||||
PK_FATAL("Unsupported simulator: %s\n", simulator.c_str());
|
||||
}
|
||||
|
||||
data["__TRACE__"] =
|
||||
sv_dump_wave.length() > 0 ?
|
||||
wave_file_name.substr(wave_file_name.find_last_of(".") + 1,
|
||||
wave_file_name.length()) :
|
||||
"OFF";
|
||||
data["__TRACE__"] = sv_dump_wave.length() > 0 ? wave_file_name.substr(wave_file_name.find_last_of(".") + 1,
|
||||
wave_file_name.length()) :
|
||||
"OFF";
|
||||
data["__SV_DUMP_WAVE__"] = sv_dump_wave;
|
||||
}
|
||||
|
||||
void render_signal_tree(
|
||||
const std::vector<picker::sv_signal_define> &external_pin,
|
||||
const std::vector<picker::sv_signal_define> &internal_signal,
|
||||
std::string &signal_tree, nlohmann::json &signal_tree_json)
|
||||
void render_signal_tree(const std::vector<picker::sv_signal_define> &external_pin,
|
||||
const std::vector<picker::sv_signal_define> &internal_signal, std::string &signal_tree,
|
||||
nlohmann::json &signal_tree_json)
|
||||
{
|
||||
// iterate the signal pin and generate the signal tree by TRIE tree
|
||||
// get all the signal name and sort them
|
||||
|
@ -197,9 +180,8 @@ namespace picker { namespace codegen {
|
|||
for (auto pin : internal_signal) { signal_list.push_back(pin); }
|
||||
|
||||
// sort the signal list for handle the signal tree
|
||||
std::sort(
|
||||
signal_list.begin(), signal_list.end(),
|
||||
[](auto &a, auto &b) { return a.logic_pin < b.logic_pin; });
|
||||
std::sort(signal_list.begin(), signal_list.end(),
|
||||
[](auto &a, auto &b) { return a.logic_pin < b.logic_pin; });
|
||||
|
||||
// split the string by delimiter, only considering the last one in
|
||||
// consecutive delimiters AAA__1_BBB_C => (AAA_, 1, BBB, C)
|
||||
|
@ -213,8 +195,7 @@ namespace picker { namespace codegen {
|
|||
last_was_delimiter = true;
|
||||
} else {
|
||||
if (last_was_delimiter) {
|
||||
tokens.push_back(
|
||||
ss.str().substr(0, ss.str().size() - 1));
|
||||
tokens.push_back(ss.str().substr(0, ss.str().size() - 1));
|
||||
ss.str("");
|
||||
}
|
||||
ss << ch;
|
||||
|
@ -236,12 +217,10 @@ namespace picker { namespace codegen {
|
|||
// Build the TRIE
|
||||
TrieNode *root = new TrieNode();
|
||||
for (auto signal : signal_list) {
|
||||
std::vector<std::string> signal_split =
|
||||
split(replace_all(signal.logic_pin, ".", "_"), '_');
|
||||
TrieNode *current = root;
|
||||
std::vector<std::string> signal_split = split(replace_all(signal.logic_pin, ".", "_"), '_');
|
||||
TrieNode *current = root;
|
||||
for (auto part_name : signal_split) {
|
||||
if (current->children.find(part_name)
|
||||
== current->children.end()) {
|
||||
if (current->children.find(part_name) == current->children.end()) {
|
||||
TrieNode *new_node = new TrieNode();
|
||||
new_node->part_name = part_name;
|
||||
current->children[part_name] = new_node;
|
||||
|
@ -258,18 +237,14 @@ namespace picker { namespace codegen {
|
|||
// number, merge them, (AAA_, 1, BBB, C) => (AAA_, 1, BBB_C)
|
||||
auto is_number = [](const std::string &s) {
|
||||
return !s.empty()
|
||||
&& std::find_if(s.begin(), s.end(), [](unsigned char c) {
|
||||
return !std::isdigit(c);
|
||||
}) == s.end();
|
||||
&& std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
|
||||
};
|
||||
|
||||
std::function<void(TrieNode *)> merge_trie = [&](TrieNode *node) {
|
||||
while (node->children.size() == 1 && !is_number(node->part_name)
|
||||
&& !is_number(node->children.begin()->first)) {
|
||||
auto child = node->children.begin();
|
||||
if (node->part_name.size() > 0) {
|
||||
node->part_name += "_";
|
||||
}
|
||||
if (node->part_name.size() > 0) { node->part_name += "_"; }
|
||||
node->part_name += child->second->part_name;
|
||||
TrieNode *temp = child->second;
|
||||
node->children.clear();
|
||||
|
@ -289,41 +264,38 @@ namespace picker { namespace codegen {
|
|||
for (auto &child : node->children) { merge_trie(child.second); }
|
||||
};
|
||||
merge_trie(root);
|
||||
if( root->part_name != "" ) {
|
||||
TrieNode *new_root = new TrieNode();
|
||||
if (root->part_name != "") {
|
||||
TrieNode *new_root = new TrieNode();
|
||||
new_root->children[root->part_name] = root;
|
||||
root = new_root;
|
||||
root = new_root;
|
||||
} // if root is not empty, json generator may lost the root part
|
||||
|
||||
// convert the TRIE to json
|
||||
std::function<void(TrieNode *, nlohmann::json &)> trie_to_json =
|
||||
[&](TrieNode *node, nlohmann::json &json) {
|
||||
if (node->isEndOfWord) {
|
||||
json["Pin"] = node->pin_type;
|
||||
json["High"] = node->high_bit;
|
||||
json["Low"] = node->low_bit;
|
||||
json["_"] = true;
|
||||
std::function<void(TrieNode *, nlohmann::json &)> trie_to_json = [&](TrieNode *node, nlohmann::json &json) {
|
||||
if (node->isEndOfWord) {
|
||||
json["Pin"] = node->pin_type;
|
||||
json["High"] = node->high_bit;
|
||||
json["Low"] = node->low_bit;
|
||||
json["_"] = true;
|
||||
}
|
||||
std::vector<std::pair<std::string, std::string>> rename_keys;
|
||||
for (const auto &child : node->children) {
|
||||
if (child.first != child.second->part_name) {
|
||||
PK_DEBUG("JSON child rename %s to %s", child.first.c_str(), child.second->part_name.c_str());
|
||||
rename_keys.emplace_back(child.first, child.second->part_name);
|
||||
}
|
||||
std::vector<std::pair<std::string, std::string>> rename_keys;
|
||||
for (const auto &child : node->children) {
|
||||
if (child.first != child.second->part_name) {
|
||||
PK_DEBUG("JSON child rename %s to %s",
|
||||
child.first.c_str(),
|
||||
child.second->part_name.c_str());
|
||||
rename_keys.emplace_back(child.first, child.second->part_name);
|
||||
}
|
||||
}
|
||||
for (const auto &rename : rename_keys) {
|
||||
node->children[rename.second] = node->children[rename.first];
|
||||
node->children.erase(rename.first);
|
||||
}
|
||||
for (auto &child : node->children) {
|
||||
PK_DEBUG("JSON child %s", child.first.c_str());
|
||||
nlohmann::json child_json;
|
||||
trie_to_json(child.second, child_json);
|
||||
json[child.first] = child_json;
|
||||
}
|
||||
};
|
||||
}
|
||||
for (const auto &rename : rename_keys) {
|
||||
node->children[rename.second] = node->children[rename.first];
|
||||
node->children.erase(rename.first);
|
||||
}
|
||||
for (auto &child : node->children) {
|
||||
PK_DEBUG("JSON child %s", child.first.c_str());
|
||||
nlohmann::json child_json;
|
||||
trie_to_json(child.second, child_json);
|
||||
json[child.first] = child_json;
|
||||
}
|
||||
};
|
||||
|
||||
// json2string
|
||||
nlohmann::json &tries = signal_tree_json;
|
||||
|
@ -332,9 +304,7 @@ namespace picker { namespace codegen {
|
|||
|
||||
// free the memory
|
||||
std::function<void(TrieNode *)> delete_trie = [&](TrieNode *node) {
|
||||
for (auto &child : node->children) {
|
||||
delete_trie(child.second);
|
||||
}
|
||||
for (auto &child : node->children) { delete_trie(child.second); }
|
||||
delete node;
|
||||
};
|
||||
delete_trie(root);
|
||||
|
@ -345,7 +315,7 @@ namespace picker { namespace codegen {
|
|||
inja::Environment env;
|
||||
nlohmann::json data;
|
||||
data["__LIB_DPI_FUNC_NAME_HASH__"] = std::string(lib_random_hash);
|
||||
extend_sv = env.render(dpi_finish_sv_template, data);
|
||||
extend_sv = env.render(dpi_finish_sv_template, data);
|
||||
}
|
||||
|
||||
} // namespace sv
|
||||
|
@ -355,22 +325,18 @@ namespace picker { namespace codegen {
|
|||
/// @param global_render_data
|
||||
/// @param external_pin
|
||||
/// @param internal_signal
|
||||
std::vector<picker::sv_signal_define>
|
||||
gen_sv_param(nlohmann::json &global_render_data,
|
||||
const std::vector<picker::sv_module_define> &sv_module_result,
|
||||
const std::vector<picker::sv_signal_define> &internal_signal,
|
||||
nlohmann::json &signal_tree_json,
|
||||
const std::string &wave_file_name,
|
||||
const std::string &simulator)
|
||||
std::vector<picker::sv_signal_define> gen_sv_param(nlohmann::json &global_render_data,
|
||||
const std::vector<picker::sv_module_define> &sv_module_result,
|
||||
const std::vector<picker::sv_signal_define> &internal_signal,
|
||||
nlohmann::json &signal_tree_json,
|
||||
const std::string &wave_file_name, const std::string &simulator)
|
||||
{
|
||||
std::string inner_modules, logic, wire, dpi_export, dpi_impl, signal_tree, extend_sv;
|
||||
|
||||
auto external_pin = sv::render_external_pin(sv_module_result, inner_modules, logic, wire,
|
||||
dpi_export, dpi_impl);
|
||||
auto external_pin = sv::render_external_pin(sv_module_result, inner_modules, logic, wire, dpi_export, dpi_impl);
|
||||
sv::render_internal_signal(internal_signal, dpi_export, dpi_impl);
|
||||
sv::render_sv_waveform(simulator, wave_file_name, global_render_data);
|
||||
sv::render_signal_tree(external_pin, internal_signal, signal_tree,
|
||||
signal_tree_json);
|
||||
sv::render_signal_tree(external_pin, internal_signal, signal_tree, signal_tree_json);
|
||||
sv::render_extend_sv(global_render_data, extend_sv);
|
||||
|
||||
global_render_data["__LOGIC_PIN_DECLARATION__"] = logic;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
namespace picker { namespace codegen {
|
||||
|
||||
void gen_uvm_code(inja::json data,std::string templateName,std::string outputName){
|
||||
|
||||
//std::cout << className << std::endl;
|
||||
void gen_uvm_code(inja::json data, std::string templateName, std::string outputName)
|
||||
{
|
||||
// std::cout << className << std::endl;
|
||||
std::ifstream template_file(templateName);
|
||||
std::string template_str((std::istreambuf_iterator<char>(template_file)), std::istreambuf_iterator<char>());
|
||||
template_file.close();
|
||||
|
@ -18,62 +18,56 @@ namespace picker { namespace codegen {
|
|||
}
|
||||
|
||||
// namespace sv
|
||||
void gen_uvm_param(picker::pack_opts &opts,uvm_transaction_define transaction,std::string filename){
|
||||
|
||||
void gen_uvm_param(picker::pack_opts &opts, uvm_transaction_define transaction, std::string filename)
|
||||
{
|
||||
std::string folderPath = filename;
|
||||
if(std::filesystem::exists(filename) && !opts.force)
|
||||
{
|
||||
if (std::filesystem::exists(filename) && !opts.force) {
|
||||
PK_MESSAGE("folder already exists");
|
||||
exit(0);
|
||||
}else {
|
||||
if(std::filesystem::exists(filename)){
|
||||
std::filesystem::path folderPath = filename;
|
||||
std::filesystem::remove_all(filename);
|
||||
}
|
||||
std::filesystem::create_directory(filename);
|
||||
if (opts.example){
|
||||
std::filesystem::create_directory(filename+"/example");
|
||||
} else {
|
||||
if (std::filesystem::exists(filename)) {
|
||||
std::filesystem::path folderPath = filename;
|
||||
std::filesystem::remove_all(filename);
|
||||
}
|
||||
std::filesystem::create_directory(filename);
|
||||
if (opts.example) { std::filesystem::create_directory(filename + "/example"); }
|
||||
}
|
||||
|
||||
inja::json data;
|
||||
std::string erro_message;
|
||||
auto python_location =
|
||||
picker::get_xcomm_lib("python/xspcomm", erro_message);
|
||||
auto python_location = picker::get_xcomm_lib("python/xspcomm", erro_message);
|
||||
if (python_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
data["__XSPCOMM_PYTHON__"] = python_location;
|
||||
auto xspcomm_include_location =
|
||||
picker::get_xcomm_lib("include", erro_message);
|
||||
data["__XSPCOMM_PYTHON__"] = python_location;
|
||||
auto xspcomm_include_location = picker::get_xcomm_lib("include", erro_message);
|
||||
if (python_location.empty()) { PK_FATAL("%s\n", erro_message.c_str()); }
|
||||
data["__XSPCOMM_INCLUDE__"] = xspcomm_include_location;
|
||||
data["variables"] = inja::json::array();
|
||||
data["useType"] = 1;
|
||||
data["filepath"] = transaction.filepath;
|
||||
data["version"] = transaction.version;
|
||||
data["datenow"] = transaction.data_now;
|
||||
data["className"] = transaction.name;
|
||||
int byte_stream_count= 0;
|
||||
for (int i = 0; i<transaction.parameters.size(); i++){
|
||||
data["variables"] = inja::json::array();
|
||||
data["useType"] = 1;
|
||||
data["filepath"] = transaction.filepath;
|
||||
data["version"] = transaction.version;
|
||||
data["datenow"] = transaction.data_now;
|
||||
data["className"] = transaction.name;
|
||||
int byte_stream_count = 0;
|
||||
for (int i = 0; i < transaction.parameters.size(); i++) {
|
||||
inja::json parameter;
|
||||
parameter["nums"] = transaction.parameters[i].byte_count;
|
||||
parameter["bit_count"] = transaction.parameters[i].bit_count;
|
||||
parameter["macro"] = transaction.parameters[i].is_marcro;
|
||||
parameter["name"] = transaction.parameters[i].name;
|
||||
parameter["macro_name"] = transaction.parameters[i].macro_name;
|
||||
parameter["nums"] = transaction.parameters[i].byte_count;
|
||||
parameter["bit_count"] = transaction.parameters[i].bit_count;
|
||||
parameter["macro"] = transaction.parameters[i].is_marcro;
|
||||
parameter["name"] = transaction.parameters[i].name;
|
||||
parameter["macro_name"] = transaction.parameters[i].macro_name;
|
||||
parameter["start_index"] = "0";
|
||||
parameter["end_index"] = "0";
|
||||
parameter["end_index"] = "0";
|
||||
data["variables"].push_back(parameter);
|
||||
byte_stream_count += transaction.parameters[i].byte_count;
|
||||
}
|
||||
data["byte_stream_count"] = byte_stream_count;
|
||||
std::string template_path = picker::get_template_path();
|
||||
gen_uvm_code(data,template_path+"/uvm/xagent.py",filename+"/"+filename+"_xagent"+".py");
|
||||
gen_uvm_code(data,template_path+"/uvm/xagent.sv",filename+"/"+filename+"_xagent.sv");
|
||||
gen_uvm_code(data,template_path+"/uvm/example_python.py",filename+"/example/"+"example_python.py");
|
||||
gen_uvm_code(data,template_path+"/uvm/example_uvm.sv",filename+"/example/"+"example_uvm.sv");
|
||||
gen_uvm_code(data,template_path+"/uvm/Makefile",filename+"/example/"+"Makefile");
|
||||
gen_uvm_code(data, template_path + "/uvm/xagent.py", filename + "/" + filename + "_xagent" + ".py");
|
||||
gen_uvm_code(data, template_path + "/uvm/xagent.sv", filename + "/" + filename + "_xagent.sv");
|
||||
gen_uvm_code(data, template_path + "/uvm/example_python.py", filename + "/example/" + "example_python.py");
|
||||
gen_uvm_code(data, template_path + "/uvm/example_uvm.sv", filename + "/example/" + "example_uvm.sv");
|
||||
gen_uvm_code(data, template_path + "/uvm/Makefile", filename + "/example/" + "Makefile");
|
||||
std::cout << "generate " + filename + " code successfully." << std::endl;
|
||||
|
||||
}
|
||||
|
||||
}} // namespace picker::codegen
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
namespace picker { namespace parser {
|
||||
|
||||
void recursive_parse(YAML::Node node,
|
||||
std::vector<picker::sv_signal_define> &pin_list,
|
||||
std::string prefix)
|
||||
void recursive_parse(YAML::Node node, std::vector<picker::sv_signal_define> &pin_list, std::string prefix)
|
||||
{
|
||||
if (node.IsMap()) {
|
||||
for (auto it = node.begin(); it != node.end(); ++it) {
|
||||
|
@ -15,19 +13,14 @@ namespace picker { namespace parser {
|
|||
recursive_parse(it->second, pin_list, prefix + "." + key);
|
||||
}
|
||||
} else if (node.IsSequence()) {
|
||||
for (auto it = node.begin(); it != node.end(); ++it) {
|
||||
recursive_parse(*it, pin_list, prefix);
|
||||
}
|
||||
for (auto it = node.begin(); it != node.end(); ++it) { recursive_parse(*it, pin_list, prefix); }
|
||||
} else if (node.IsScalar()) {
|
||||
sv_signal_define pin;
|
||||
std::string value =
|
||||
node.as<std::string>(); // such as "input [31:0] Signalname"
|
||||
std::string value = node.as<std::string>(); // such as "input [31:0] Signalname"
|
||||
std::vector<std::string> tokens;
|
||||
std::string token;
|
||||
std::istringstream tokenStream(value);
|
||||
while (std::getline(tokenStream, token, ' ')) {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
while (std::getline(tokenStream, token, ' ')) { tokens.push_back(token); }
|
||||
if (tokens.size() == 2) {
|
||||
pin.logic_pin = prefix + "." + tokens[1];
|
||||
pin.logic_pin_type = tokens[0];
|
||||
|
@ -37,8 +30,7 @@ namespace picker { namespace parser {
|
|||
pin.logic_pin_type = tokens[0];
|
||||
int pos = tokens[1].find(":");
|
||||
pin.logic_pin_hb = std::stoi(tokens[1].substr(1, pos - 1));
|
||||
pin.logic_pin_lb = std::stoi(
|
||||
tokens[1].substr(pos + 1, tokens[1].length() - pos - 2));
|
||||
pin.logic_pin_lb = std::stoi(tokens[1].substr(pos + 1, tokens[1].length() - pos - 2));
|
||||
|
||||
} else {
|
||||
PK_MESSAGE("error: unknown node type");
|
||||
|
@ -57,12 +49,9 @@ namespace picker { namespace parser {
|
|||
return pin_list;
|
||||
};
|
||||
|
||||
int internal(picker::export_opts &opts,
|
||||
std::vector<picker::sv_signal_define> &internal_pin)
|
||||
int internal(picker::export_opts &opts, std::vector<picker::sv_signal_define> &internal_pin)
|
||||
{
|
||||
internal_pin = opts.internal.length() == 0 ?
|
||||
std::vector<picker::sv_signal_define>() :
|
||||
internal(opts.internal);
|
||||
internal_pin = opts.internal.length() == 0 ? std::vector<picker::sv_signal_define>() : internal(opts.internal);
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,19 +2,15 @@
|
|||
#include "parser/sv.hpp"
|
||||
#include "parser/exprtk.hpp"
|
||||
|
||||
#define token_res(i) \
|
||||
(std::string(module_token[i]["tag"])).size() > 1 ? \
|
||||
(std::string)module_token[i]["text"] : \
|
||||
(std::string)module_token[i]["tag"]
|
||||
#define token_res(i) \
|
||||
(std::string(module_token[i]["tag"])).size() > 1 ? (std::string)module_token[i]["text"] : \
|
||||
(std::string)module_token[i]["tag"]
|
||||
|
||||
#define param_res(var) parameter_var.count(var) ? parameter_var[var] : var
|
||||
|
||||
namespace picker { namespace parser {
|
||||
|
||||
|
||||
|
||||
std::vector<picker::sv_signal_define> sv_pin(nlohmann::json &module_token,
|
||||
std::string &src_module_name)
|
||||
std::vector<picker::sv_signal_define> sv_pin(nlohmann::json &module_token, std::string &src_module_name)
|
||||
{
|
||||
// nlohmann::json res_token;
|
||||
// for (auto it = module_token.begin(); it != module_token.end();) {
|
||||
|
@ -38,8 +34,7 @@ namespace picker { namespace parser {
|
|||
std::map<std::string, std::string> parameter_var;
|
||||
std::vector<picker::sv_signal_define> pin;
|
||||
for (int j = 0; j < module_token.size(); j++)
|
||||
if (module_token[j]["tag"] == "module"
|
||||
&& module_token[j + 1]["text"] == src_module_name) {
|
||||
if (module_token[j]["tag"] == "module" && module_token[j + 1]["text"] == src_module_name) {
|
||||
std::string pin_type, pin_high, pin_low;
|
||||
for (int i = j + 2; i < module_token.size(); i++) {
|
||||
PK_DEBUG("%s", module_token[i]["tag"].dump().c_str());
|
||||
|
@ -49,23 +44,21 @@ namespace picker { namespace parser {
|
|||
continue;
|
||||
}
|
||||
// Record pin type
|
||||
if (module_token[i]["tag"] == "input"
|
||||
|| module_token[i]["tag"] == "output"
|
||||
if (module_token[i]["tag"] == "input" || module_token[i]["tag"] == "output"
|
||||
|| module_token[i]["tag"] == "inout") {
|
||||
pin_type = module_token[i]["tag"];
|
||||
pin_high.clear();
|
||||
pin_low.clear();
|
||||
// Skip logic, wire, reg type. We export pins with logic type, these types are not needed yet.
|
||||
i++;
|
||||
if( module_token[i]["tag"] == "logic" || module_token[i]["tag"] == "wire" || module_token[i]["tag"] == "reg" ) {
|
||||
if (module_token[i]["tag"] == "logic" || module_token[i]["tag"] == "wire"
|
||||
|| module_token[i]["tag"] == "reg") {
|
||||
i++;
|
||||
}
|
||||
// Parse pin length
|
||||
if (module_token[i]["tag"] == "[") {
|
||||
while (module_token[++i]["tag"] != ":")
|
||||
pin_high += param_res(token_res(i));
|
||||
while (module_token[++i]["tag"] != "]")
|
||||
pin_low += param_res(token_res(i));
|
||||
while (module_token[++i]["tag"] != ":") pin_high += param_res(token_res(i));
|
||||
while (module_token[++i]["tag"] != "]") pin_low += param_res(token_res(i));
|
||||
} else {
|
||||
i--;
|
||||
pin_high = "-1";
|
||||
|
@ -76,17 +69,14 @@ namespace picker { namespace parser {
|
|||
|
||||
if (pin_type == "parameter") {
|
||||
if (module_token[i]["tag"] == "SymbolIdentifier") {
|
||||
std::string parameter_name =
|
||||
module_token[i++]["text"];
|
||||
std::string parameter_name = module_token[i++]["text"];
|
||||
std::string parameter_value;
|
||||
while (module_token[++i]["tag"] != ","
|
||||
&& module_token[i]["tag"] != ")") {
|
||||
while (module_token[++i]["tag"] != "," && module_token[i]["tag"] != ")") {
|
||||
parameter_value += param_res(token_res(i));
|
||||
}
|
||||
parameter_var[parameter_name] = parameter_value;
|
||||
PK_DEBUG("parameter_name: %s, parameter_value: %s",
|
||||
parameter_name.c_str(),
|
||||
parameter_value.c_str());
|
||||
PK_DEBUG("parameter_name: %s, parameter_value: %s", parameter_name.c_str(),
|
||||
parameter_value.c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -96,13 +86,10 @@ namespace picker { namespace parser {
|
|||
exprtk::expression<double> expression;
|
||||
auto calc_pin_length = [&](const std::string &exp) {
|
||||
if (parser.compile(exp, expression)) {
|
||||
PK_DEBUG("pin length expression: %s as %f",
|
||||
exp.c_str(), expression.value());
|
||||
PK_DEBUG("pin length expression: %s as %f", exp.c_str(), expression.value());
|
||||
return expression.value();
|
||||
} else {
|
||||
PK_FATAL(
|
||||
"Failed to parse pin length expression: %s .\n",
|
||||
exp.c_str());
|
||||
PK_FATAL("Failed to parse pin length expression: %s .\n", exp.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -110,8 +97,7 @@ namespace picker { namespace parser {
|
|||
sv_signal_define tmp_pin;
|
||||
tmp_pin.logic_pin_type = pin_type;
|
||||
|
||||
if (module_token[i]["tag"]
|
||||
== "SymbolIdentifier") { // Noraml pin
|
||||
if (module_token[i]["tag"] == "SymbolIdentifier") { // Noraml pin
|
||||
tmp_pin.logic_pin = module_token[i]["text"];
|
||||
if (pin_high != "-1") {
|
||||
tmp_pin.logic_pin_hb = calc_pin_length(pin_high);
|
||||
|
@ -131,57 +117,54 @@ namespace picker { namespace parser {
|
|||
return pin;
|
||||
}
|
||||
|
||||
std::map<std::string, int> parse_mname_and_numbers(std::vector<std::string> &name_and_nums){
|
||||
std::map<std::string, int> parse_mname_and_numbers(std::vector<std::string> &name_and_nums)
|
||||
{
|
||||
// eg: MouduleA,1,ModuleB,3,MouldeC,ModuleE,ModuleF
|
||||
std::string m_name = "";
|
||||
int num = 1;
|
||||
int num = 1;
|
||||
std::map<std::string, int> ret;
|
||||
for(auto v : name_and_nums){
|
||||
v = picker::trim(v);
|
||||
for (auto v : name_and_nums) {
|
||||
v = picker::trim(v);
|
||||
num = 1;
|
||||
if(picker::str_start_with_digit(v)){
|
||||
if (picker::str_start_with_digit(v)) {
|
||||
num = std::stoi(v);
|
||||
if(!m_name.empty()){
|
||||
if (!m_name.empty()) {
|
||||
ret[m_name] = num;
|
||||
m_name = "";
|
||||
}else{
|
||||
m_name = "";
|
||||
} else {
|
||||
PK_MESSAGE("Ignore num: %d, no matched Module find", num)
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
vassert(!v.empty(), "Find empty Module name in --sname arg");
|
||||
if(!m_name.empty()){
|
||||
ret[m_name] = num;
|
||||
}
|
||||
if (!m_name.empty()) { ret[m_name] = num; }
|
||||
m_name = v;
|
||||
}
|
||||
}
|
||||
if(!m_name.empty())ret[m_name] = 1;
|
||||
if (!m_name.empty()) ret[m_name] = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::map<std::string, nlohmann::json> match_module_with_file(
|
||||
std::vector<std::string> files, std::vector<std::string> m_names
|
||||
){
|
||||
std::map<std::string, nlohmann::json> match_module_with_file(std::vector<std::string> files,
|
||||
std::vector<std::string> m_names)
|
||||
{
|
||||
std::map<std::string, nlohmann::json> ret;
|
||||
for(auto f: files){
|
||||
std::string fpath = "/tmp/" + std::filesystem::path(f).filename().string() + std::string(lib_random_hash) + picker::get_node_uuid() + ".json";
|
||||
std::string syntax_cmd =
|
||||
"verible-verilog-syntax --export_json --printtokens " + f
|
||||
+ "> " + fpath;
|
||||
for (auto f : files) {
|
||||
std::string fpath = "/tmp/" + std::filesystem::path(f).filename().string() + std::string(lib_random_hash)
|
||||
+ picker::get_node_uuid() + ".json";
|
||||
std::string syntax_cmd = "verible-verilog-syntax --export_json --printtokens " + f + "> " + fpath;
|
||||
exec(syntax_cmd.c_str());
|
||||
auto mjson = nlohmann::json::parse(read_file(fpath));
|
||||
std::vector<std::string> module_list;
|
||||
auto module_token = mjson[f]["tokens"];
|
||||
for (int i = 0; i < module_token.size(); i++){
|
||||
if (module_token[i]["tag"] == "module")
|
||||
module_list.push_back(module_token[i + 1]["text"]);
|
||||
for (int i = 0; i < module_token.size(); i++) {
|
||||
if (module_token[i]["tag"] == "module") module_list.push_back(module_token[i + 1]["text"]);
|
||||
}
|
||||
if(m_names.empty()){
|
||||
if (m_names.empty()) {
|
||||
ret[module_list.back()] = module_token;
|
||||
return ret;
|
||||
}
|
||||
for(auto m: m_names){
|
||||
if(picker::contians(module_list, m)){
|
||||
for (auto m : m_names) {
|
||||
if (picker::contians(module_list, m)) {
|
||||
PK_MESSAGE("find module: %s in file: %s", m.c_str(), f.c_str())
|
||||
ret[m] = module_token;
|
||||
// todo: can be optimized, only collect matched module tokens instead of all tokens in this file
|
||||
|
@ -190,9 +173,7 @@ namespace picker { namespace parser {
|
|||
PK_DEBUG("rm -f %s", fpath.c_str());
|
||||
exec(("rm -f " + fpath).c_str());
|
||||
}
|
||||
for(auto m: m_names){
|
||||
vassert(ret.count(m), "Module: " + m + " not find in input file");
|
||||
}
|
||||
for (auto m : m_names) { vassert(ret.count(m), "Module: " + m + " not find in input file"); }
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -203,34 +184,30 @@ namespace picker { namespace parser {
|
|||
std::map<std::string, nlohmann::json> m_json;
|
||||
std::map<std::string, int> m_nums;
|
||||
|
||||
if(opts.source_module_name_list.empty()){
|
||||
if(opts.file.size()!=1)
|
||||
PK_FATAL("When module name not given (--sname),"
|
||||
" can only parse one .v/.sv file (%d find!)", (int)opts.file.size())
|
||||
m_json = match_module_with_file(opts.file, opts.source_module_name_list);
|
||||
if (opts.source_module_name_list.empty()) {
|
||||
if (opts.file.size() != 1)
|
||||
PK_FATAL("When module name not given (--sname),"
|
||||
" can only parse one .v/.sv file (%d find!)",
|
||||
(int)opts.file.size())
|
||||
m_json = match_module_with_file(opts.file, opts.source_module_name_list);
|
||||
m_names = picker::key_as_vector(m_json);
|
||||
for(auto &v: m_names){
|
||||
m_nums[v] = 1;
|
||||
}
|
||||
}else{
|
||||
m_nums = parse_mname_and_numbers(opts.source_module_name_list);
|
||||
for (auto &v : m_names) { m_nums[v] = 1; }
|
||||
} else {
|
||||
m_nums = parse_mname_and_numbers(opts.source_module_name_list);
|
||||
m_names = picker::key_as_vector(m_nums);
|
||||
m_json = match_module_with_file(opts.file, m_names);
|
||||
m_json = match_module_with_file(opts.file, m_names);
|
||||
}
|
||||
|
||||
auto target_name = picker::join_str_vec(m_names, "_");
|
||||
for(auto &v: m_json){
|
||||
for (auto &v : m_json) {
|
||||
picker::sv_module_define sv_module;
|
||||
sv_module.module_name = v.first;
|
||||
sv_module.module_nums = m_nums[sv_module.module_name];
|
||||
sv_module.pins = sv_pin(v.second, sv_module.module_name);
|
||||
sv_module.pins = sv_pin(v.second, sv_module.module_name);
|
||||
sv_module_result.push_back(sv_module);
|
||||
}
|
||||
|
||||
|
||||
opts.target_module_name = opts.target_module_name.size() == 0 ?
|
||||
target_name:
|
||||
opts.target_module_name;
|
||||
opts.target_module_name = opts.target_module_name.size() == 0 ? target_name : opts.target_module_name;
|
||||
if (opts.target_dir.size() == 0 || opts.target_dir.back() == '/') {
|
||||
opts.target_dir += opts.target_module_name;
|
||||
PK_DEBUG("Set target dir to target module name: %s", opts.target_dir.c_str());
|
||||
|
@ -238,9 +215,8 @@ namespace picker { namespace parser {
|
|||
for (auto &m : sv_module_result) {
|
||||
PK_DEBUG("Module: %s, nums: %d", m.module_name.c_str(), m.module_nums);
|
||||
for (auto &p : m.pins) {
|
||||
PK_DEBUG("Pin: %s, type: %s, high: %d, low: %d",
|
||||
p.logic_pin.c_str(), p.logic_pin_type.c_str(),
|
||||
p.logic_pin_hb, p.logic_pin_lb);
|
||||
PK_DEBUG("Pin: %s, type: %s, high: %d, low: %d", p.logic_pin.c_str(), p.logic_pin_type.c_str(),
|
||||
p.logic_pin_hb, p.logic_pin_lb);
|
||||
}
|
||||
}
|
||||
PK_DEBUG("Target Module: %s", opts.target_module_name.c_str());
|
||||
|
|
|
@ -2,153 +2,152 @@
|
|||
#include "parser/sv.hpp"
|
||||
#include "parser/exprtk.hpp"
|
||||
|
||||
|
||||
namespace picker { namespace parser {
|
||||
|
||||
|
||||
void pre_process_sv(picker::pack_opts &opts, std::string filepath, std::string &filename){
|
||||
//create file
|
||||
filename = extract_name(filepath,'/',0);
|
||||
filename = extract_name(filename,'.',1);
|
||||
std::filesystem::create_directory(filename+"_tmp");
|
||||
//parse sv to json
|
||||
std::string command = "verible-verilog-syntax --export_json --printtokens "+filepath+" > "+filename + "_tmp/"+filename+".json";
|
||||
void pre_process_sv(picker::pack_opts &opts, std::string filepath, std::string &filename)
|
||||
{
|
||||
// create file
|
||||
filename = extract_name(filepath, '/', 0);
|
||||
filename = extract_name(filename, '.', 1);
|
||||
std::filesystem::create_directory(filename + "_tmp");
|
||||
// parse sv to json
|
||||
std::string command = "verible-verilog-syntax --export_json --printtokens " + filepath + " > " + filename
|
||||
+ "_tmp/" + filename + ".json";
|
||||
int result = std::system(command.c_str());
|
||||
//createDirectoryRecursive(folderPath);
|
||||
// createDirectoryRecursive(folderPath);
|
||||
if (result == 0) {
|
||||
std::cout << "parse " + filename + ".sv successfully." << std::endl;
|
||||
} else {
|
||||
std::cout << "failed to parse " + filename << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string get_macro_define(std::string macro_path, std::string macro_name) {
|
||||
std::string get_macro_define(std::string macro_path, std::string macro_name)
|
||||
{
|
||||
char current_path[PATH_MAX];
|
||||
if (getcwd(current_path, sizeof(current_path)) == nullptr) { // 使用getcwd函数获取当前工作目录
|
||||
throw std::runtime_error("Error getting current directory"); // 如果获取失败,抛出异常
|
||||
if (getcwd(current_path, sizeof(current_path)) == nullptr) { // 使用getcwd函数获取当前工作目录
|
||||
throw std::runtime_error("Error getting current directory"); // 如果获取失败,抛出异常
|
||||
}
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
std::string script_path = picker::get_template_path()+"/uvm/get_macro_value.sh";
|
||||
std::string command = script_path + " " + std::string(current_path) + "/" + macro_path + " " + macro_name;
|
||||
std::string script_path = picker::get_template_path() + "/uvm/get_macro_value.sh";
|
||||
std::string command = script_path + " " + std::string(current_path) + "/" + macro_path + " " + macro_name;
|
||||
|
||||
std::cout << command <<std::endl;
|
||||
std::cout << command << std::endl;
|
||||
|
||||
// 创建一个自定义的 deleter
|
||||
auto deleter = [](FILE* fp) { pclose(fp); };
|
||||
auto deleter = [](FILE *fp) { pclose(fp); };
|
||||
std::unique_ptr<FILE, decltype(deleter)> pipe(popen(command.c_str(), "r"), deleter);
|
||||
if (!pipe) {
|
||||
throw std::runtime_error("popen() failed!");
|
||||
}
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
if (!pipe) { throw std::runtime_error("popen() failed!"); }
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { result += buffer.data(); }
|
||||
return result;
|
||||
}
|
||||
|
||||
void handle_basic_type(std::string data_type, uvm_parameter ¶meter){
|
||||
if(data_type == "string"){
|
||||
//person_data["type"] = "str";
|
||||
}else if(data_type == "int"){
|
||||
parameter.byte_count= 4;
|
||||
parameter.bit_count = 32;
|
||||
void handle_basic_type(std::string data_type, uvm_parameter ¶meter)
|
||||
{
|
||||
if (data_type == "string") {
|
||||
// person_data["type"] = "str";
|
||||
} else if (data_type == "int") {
|
||||
parameter.byte_count = 4;
|
||||
parameter.bit_count = 32;
|
||||
|
||||
}else if(data_type == "shortint"){
|
||||
parameter.bit_count = 16;
|
||||
} else if (data_type == "shortint") {
|
||||
parameter.bit_count = 16;
|
||||
parameter.byte_count = 2;
|
||||
|
||||
}else if(data_type == "longint"){
|
||||
parameter.bit_count = 64;
|
||||
} else if (data_type == "longint") {
|
||||
parameter.bit_count = 64;
|
||||
parameter.byte_count = 8;
|
||||
|
||||
}else if(data_type == "byte"){
|
||||
parameter.bit_count = 8;
|
||||
} else if (data_type == "byte") {
|
||||
parameter.bit_count = 8;
|
||||
parameter.byte_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_array(int &j, auto &module_token, uvm_parameter ¶meter,std::string macro_path){
|
||||
void handle_array(int &j, auto &module_token, uvm_parameter ¶meter, std::string macro_path)
|
||||
{
|
||||
std::string nbits = module_token[++j]["tag"], count;
|
||||
if(module_token[j+1]["tag"] == "MacroIdentifier"){
|
||||
parameter.macro_name = extract_name(module_token[j+1]["text"],'`',0);
|
||||
if(module_token[j+2]["tag"] == "-"){
|
||||
count = get_macro_define(macro_path,extract_name(module_token[j+1]["text"],'`',0));
|
||||
if (module_token[j + 1]["tag"] == "MacroIdentifier") {
|
||||
parameter.macro_name = extract_name(module_token[j + 1]["text"], '`', 0);
|
||||
if (module_token[j + 2]["tag"] == "-") {
|
||||
count = get_macro_define(macro_path, extract_name(module_token[j + 1]["text"], '`', 0));
|
||||
parameter.bit_count = std::stod(count);
|
||||
}else{
|
||||
count = get_macro_define(macro_path,module_token[j+1]["text"]);
|
||||
parameter.bit_count = std::stod(count)+1;
|
||||
} else {
|
||||
count = get_macro_define(macro_path, module_token[j + 1]["text"]);
|
||||
parameter.bit_count = std::stod(count) + 1;
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
parameter.macro_name = "0";
|
||||
count = module_token[j+1]["text"];
|
||||
parameter.bit_count = std::stod(count)+1;
|
||||
count = module_token[j + 1]["text"];
|
||||
parameter.bit_count = std::stod(count) + 1;
|
||||
}
|
||||
parameter.byte_count = std::ceil(parameter.bit_count/8.0);
|
||||
|
||||
while(module_token[j+1]["tag"] !="]"){
|
||||
if(module_token[j+1]["tag"] ==":" || module_token[j+1]["tag"] =="-")
|
||||
nbits += module_token[++j]["tag"];
|
||||
parameter.byte_count = std::ceil(parameter.bit_count / 8.0);
|
||||
|
||||
while (module_token[j + 1]["tag"] != "]") {
|
||||
if (module_token[j + 1]["tag"] == ":" || module_token[j + 1]["tag"] == "-")
|
||||
nbits += module_token[++j]["tag"];
|
||||
else
|
||||
nbits += module_token[++j]["text"];
|
||||
}
|
||||
}
|
||||
nbits += module_token[++j]["tag"];
|
||||
parameter.name = module_token[++j]["text"];
|
||||
nbits = nbits+parameter.name;
|
||||
nbits = nbits + parameter.name;
|
||||
}
|
||||
|
||||
//解析sv文件
|
||||
uvm_transaction_define parse_sv(std::string filepath,std::string filename, std::string macro_path){
|
||||
uvm_transaction_define parse_sv(std::string filepath, std::string filename, std::string macro_path)
|
||||
{
|
||||
uvm_transaction_define transaction;
|
||||
auto json_result = read_file(filename+"_tmp/"+filename+".json");
|
||||
|
||||
auto json_result = read_file(filename + "_tmp/" + filename + ".json");
|
||||
|
||||
// 删除tmp文件夹
|
||||
std::filesystem::path deletefolderPath = filename+"_tmp";
|
||||
std::filesystem::path deletefolderPath = filename + "_tmp";
|
||||
std::filesystem::remove_all(deletefolderPath);
|
||||
nlohmann::json module_json = nlohmann::json::parse(json_result);
|
||||
std::string current_index = "0";
|
||||
|
||||
std::string current_index = "0";
|
||||
|
||||
//指明json路径
|
||||
auto module_token = module_json[filepath]["tokens"];
|
||||
inja::json data;
|
||||
transaction.filepath = filepath;
|
||||
transaction.version = version();
|
||||
transaction.version = version();
|
||||
transaction.data_now = fmtnow();
|
||||
for(int i=0;i<module_token.size();i++){
|
||||
if(module_token[i]["tag"] == "class"){
|
||||
transaction.name = module_token[i+1]["text"];
|
||||
for (int i = 0; i < module_token.size(); i++) {
|
||||
if (module_token[i]["tag"] == "class") {
|
||||
transaction.name = module_token[i + 1]["text"];
|
||||
data["className"] = transaction.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(int j=0;j<module_token.size();j++){
|
||||
std::string data_type,variableName,nbits,name1,numsstring, macro_name ;
|
||||
int numsOrigin,nums = 1,macro = 0;
|
||||
for (int j = 0; j < module_token.size(); j++) {
|
||||
std::string data_type, variableName, nbits, name1, numsstring, macro_name;
|
||||
int numsOrigin, nums = 1, macro = 0;
|
||||
uvm_parameter parameter;
|
||||
|
||||
if(module_token[j]["tag"] == "rand"){
|
||||
data_type = module_token[++j]["tag"];
|
||||
if (module_token[j]["tag"] == "rand") {
|
||||
data_type = module_token[++j]["tag"];
|
||||
parameter.byte_count = 1;
|
||||
parameter.bit_count = 1;
|
||||
parameter.bit_count = 1;
|
||||
|
||||
handle_basic_type(data_type, parameter);
|
||||
|
||||
if(module_token[j+1]["tag"] =="["){
|
||||
handle_array(j,module_token,parameter,macro_name);
|
||||
}else{
|
||||
|
||||
if (module_token[j + 1]["tag"] == "[") {
|
||||
handle_array(j, module_token, parameter, macro_name);
|
||||
} else {
|
||||
parameter.name = module_token[++j]["text"];
|
||||
}
|
||||
parameter.is_marcro = macro;
|
||||
parameter.is_marcro = macro;
|
||||
parameter.macro_name = macro_name;
|
||||
|
||||
if(macro == 1){
|
||||
if (macro == 1) {
|
||||
current_index = current_index + " + " + macro_name;
|
||||
}else {
|
||||
} else {
|
||||
current_index = current_index + " + " + std::to_string(nums);
|
||||
}
|
||||
|
||||
|
||||
transaction.parameters.push_back(parameter);
|
||||
}
|
||||
}
|
||||
|
@ -158,9 +157,9 @@ namespace picker { namespace parser {
|
|||
int uvm(picker::pack_opts &opts, std::string &path, std::string &filename, uvm_transaction_define &uvm_transaction)
|
||||
{
|
||||
std::string macro_define;
|
||||
pre_process_sv(opts,path,filename);
|
||||
uvm_transaction = parse_sv(path ,filename,macro_define);
|
||||
pre_process_sv(opts, path, filename);
|
||||
uvm_transaction = parse_sv(path, filename, macro_define);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}} // namespace picker::parser
|
179
src/picker.cpp
179
src/picker.cpp
|
@ -14,15 +14,12 @@ bool is_debug = false;
|
|||
|
||||
void check_debug()
|
||||
{
|
||||
if (std::getenv("PICKER_DEBUG") != NULL) {
|
||||
picker::is_debug = true;
|
||||
}
|
||||
if (std::getenv("PICKER_DEBUG") != NULL) { picker::is_debug = true; }
|
||||
}
|
||||
|
||||
std::string to_base62(uint64_t num)
|
||||
{
|
||||
const std::string base62_chars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
const std::string base62_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
std::string result;
|
||||
do {
|
||||
result = base62_chars[num % 62] + result;
|
||||
|
@ -33,46 +30,40 @@ std::string to_base62(uint64_t num)
|
|||
|
||||
int set_options_export_rtl(CLI::App &top_app)
|
||||
{
|
||||
auto app = top_app.add_subcommand(
|
||||
"export",
|
||||
"Export RTL Projects Sources as Software libraries such as C++/Python");
|
||||
auto app = top_app.add_subcommand("export", "Export RTL Projects Sources as Software libraries such as C++/Python");
|
||||
|
||||
// Set DUT RTL Source File, Required
|
||||
app->add_option("file", export_opts.file,
|
||||
"DUT .v/.sv source file, contain the top module")->delimiter(',')
|
||||
app->add_option("file", export_opts.file, "DUT .v/.sv source file, contain the top module")
|
||||
->delimiter(',')
|
||||
->required();
|
||||
|
||||
// Set DUT RTL Extra Source File List, Optional
|
||||
app->add_option(
|
||||
"--fs,--filelist", export_opts.filelists,
|
||||
"DUT .v/.sv source files, contain the top module, split by comma.\n"
|
||||
"Or use '*.txt' file with one RTL file path per line to specify the file list")->delimiter(',');
|
||||
app->add_option("--fs,--filelist", export_opts.filelists,
|
||||
"DUT .v/.sv source files, contain the top module, split by comma.\n"
|
||||
"Or use '*.txt' file with one RTL file path per line to specify the file list")
|
||||
->delimiter(',');
|
||||
|
||||
// Set DUT RTL Simulator, Optional, default is verilator
|
||||
app->add_option("--sim", export_opts.sim,
|
||||
"vcs or verilator as simulator, default is verilator")
|
||||
app->add_option("--sim", export_opts.sim, "vcs or verilator as simulator, default is verilator")
|
||||
->default_val("verilator");
|
||||
|
||||
// Set DUT RTL Language, Optional, default is python
|
||||
std::vector<std::string> select_languages = {"python", "cpp", "java",
|
||||
"scala", "golang"};
|
||||
app->add_option(
|
||||
"--lang,--language", export_opts.language,
|
||||
"Build example project, default is python, choose cpp, java or python")
|
||||
std::vector<std::string> select_languages = {"python", "cpp", "java", "scala", "golang"};
|
||||
app->add_option("--lang,--language", export_opts.language,
|
||||
"Build example project, default is python, choose cpp, java or python")
|
||||
->default_val("python")
|
||||
->check(CLI::IsMember(select_languages));
|
||||
|
||||
// Set DUT RTL Source Dir, Optional, default is
|
||||
// ${picker_install_path}/../picker/template
|
||||
app->add_option(
|
||||
"--sdir,--source_dir", export_opts.source_dir,
|
||||
"Template Files Dir, default is ${picker_install_path}/../picker/template")
|
||||
app->add_option("--sdir,--source_dir", export_opts.source_dir,
|
||||
"Template Files Dir, default is ${picker_install_path}/../picker/template")
|
||||
->default_val(picker::get_template_path());
|
||||
|
||||
// Set DUT RTL Source Module Name, Optional, default is the last module in
|
||||
app->add_option(
|
||||
"--sname,--source_module_name", export_opts.source_module_name_list,
|
||||
"Pick the module in DUT .v file, default is the last module in the -f marked file")->delimiter(',');
|
||||
app->add_option("--sname,--source_module_name", export_opts.source_module_name_list,
|
||||
"Pick the module in DUT .v file, default is the last module in the -f marked file")
|
||||
->delimiter(',');
|
||||
|
||||
// Set Generated Software library module name, Optional, default is the same
|
||||
app->add_option(
|
||||
|
@ -86,27 +77,24 @@ int set_options_export_rtl(CLI::App &top_app)
|
|||
->default_val("");
|
||||
|
||||
// Set DUT RTL Internal Signal Config File, Optional, default is empty
|
||||
app->add_option(
|
||||
"--internal", export_opts.internal,
|
||||
"Exported internal signal config file, default is empty, means no internal pin");
|
||||
app->add_option("--internal", export_opts.internal,
|
||||
"Exported internal signal config file, default is empty, means no internal pin");
|
||||
|
||||
// Simulate frequncy while using VCS simulator, Optional, default is 100MHz
|
||||
app->add_option(
|
||||
"-F,--frequency", export_opts.frequency,
|
||||
"Set the frequency of the **only VCS** DUT, default is 100MHz, use Hz, KHz, MHz, GHz as unit")
|
||||
app->add_option("-F,--frequency", export_opts.frequency,
|
||||
"Set the frequency of the **only VCS** DUT, default is 100MHz, use Hz, KHz, MHz, GHz as unit")
|
||||
->default_val("100MHz");
|
||||
|
||||
// Dump wave file name, Optional, default is empty means don't dump wave
|
||||
app->add_option("-w,--wave_file_name", export_opts.wave_file_name,
|
||||
"Wave file name, emtpy mean don't dump wave");
|
||||
app->add_option("-w,--wave_file_name", export_opts.wave_file_name, "Wave file name, emtpy mean don't dump wave");
|
||||
|
||||
// Enable coverage, Optional, default is OFF
|
||||
app->add_flag("-c,--coverage", export_opts.coverage,
|
||||
"Enable coverage, default is not selected as OFF");
|
||||
app->add_flag("-c,--coverage", export_opts.coverage, "Enable coverage, default is not selected as OFF");
|
||||
|
||||
// Enable copy xspcomm lib to DUT location
|
||||
app->add_option("--cp_lib, --copy_xspcomm_lib", export_opts.cp_lib,
|
||||
"Copy xspcomm lib to generated DUT dir, default is true")->default_val(true);
|
||||
"Copy xspcomm lib to generated DUT dir, default is true")
|
||||
->default_val(true);
|
||||
|
||||
// User defined simulator compile args, passthrough. Eg: '-v -x-assign=fast
|
||||
// -Wall --trace' || '-C vcs -cc -f filelist.f'
|
||||
|
@ -116,9 +104,8 @@ int set_options_export_rtl(CLI::App &top_app)
|
|||
|
||||
// User defined gcc/clang compile command, passthrough. Eg:'-O3 -std=c++17
|
||||
// -I./include'
|
||||
app->add_option(
|
||||
"-C,--cflag", export_opts.cflag,
|
||||
"User defined gcc/clang compile command, passthrough. Eg:'-O3 -std=c++17 -I./include'");
|
||||
app->add_option("-C,--cflag", export_opts.cflag,
|
||||
"User defined gcc/clang compile command, passthrough. Eg:'-O3 -std=c++17 -I./include'");
|
||||
|
||||
// app->add_option(
|
||||
// "-r,--rename", export_opts.rename,
|
||||
|
@ -126,10 +113,8 @@ int set_options_export_rtl(CLI::App &top_app)
|
|||
// -std=c++17 -I./include'");
|
||||
|
||||
app->add_flag("--verbose", export_opts.verbose, "Verbose mode");
|
||||
app->add_flag("-e,--example", export_opts.example,
|
||||
"Build example project, default is OFF");
|
||||
app->add_option("--autobuild", export_opts.autobuild,
|
||||
"Auto build the generated project, default is true")
|
||||
app->add_flag("-e,--example", export_opts.example, "Build example project, default is OFF");
|
||||
app->add_option("--autobuild", export_opts.autobuild, "Auto build the generated project, default is true")
|
||||
->default_val(true);
|
||||
|
||||
return 0;
|
||||
|
@ -137,24 +122,16 @@ int set_options_export_rtl(CLI::App &top_app)
|
|||
|
||||
int set_options_pack_message(CLI::App &top_app)
|
||||
{
|
||||
auto app = top_app.add_subcommand(
|
||||
"pack", "Pack UVM transaction as a UVM agent and Python class");
|
||||
auto app = top_app.add_subcommand("pack", "Pack UVM transaction as a UVM agent and Python class");
|
||||
|
||||
// Set DUT RTL Source File, Required
|
||||
app->add_flag(
|
||||
"-e,--example", pack_opts.example,
|
||||
"Generate example project based on transaction, default is OFF");
|
||||
app->add_flag("-e,--example", pack_opts.example, "Generate example project based on transaction, default is OFF");
|
||||
|
||||
app->add_flag(
|
||||
"-c,--force", pack_opts.force,
|
||||
"Force delete folder when the code has already generated by picker");
|
||||
app->add_flag("-c,--force", pack_opts.force, "Force delete folder when the code has already generated by picker");
|
||||
|
||||
app->add_option("file", pack_opts.files,
|
||||
"Sv source file, contain the transaction define")
|
||||
->required();
|
||||
app->add_option("file", pack_opts.files, "Sv source file, contain the transaction define")->required();
|
||||
|
||||
app->add_option("-r,--rename", pack_opts.rename,
|
||||
"Rename transaction name in picker generate code");
|
||||
app->add_option("-r,--rename", pack_opts.rename, "Rename transaction name in picker generate code");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -162,26 +139,18 @@ int set_options_pack_message(CLI::App &top_app)
|
|||
int set_options_main(CLI::App &app)
|
||||
{
|
||||
app.add_flag("-v, --version", main_opts.version, "Print version");
|
||||
app.add_flag("--show_default_template_path",
|
||||
main_opts.show_default_template_path,
|
||||
"Print default template path");
|
||||
app.add_flag("--show_xcom_lib_location_cpp",
|
||||
main_opts.show_xcom_lib_location_cpp,
|
||||
app.add_flag("--show_default_template_path", main_opts.show_default_template_path, "Print default template path");
|
||||
app.add_flag("--show_xcom_lib_location_cpp", main_opts.show_xcom_lib_location_cpp,
|
||||
"Print xspcomm lib and include location");
|
||||
app.add_flag("--show_xcom_lib_location_java",
|
||||
main_opts.show_xcom_lib_location_java,
|
||||
app.add_flag("--show_xcom_lib_location_java", main_opts.show_xcom_lib_location_java,
|
||||
"Print xspcomm-java.jar location");
|
||||
app.add_flag("--show_xcom_lib_location_scala",
|
||||
main_opts.show_xcom_lib_location_scala,
|
||||
app.add_flag("--show_xcom_lib_location_scala", main_opts.show_xcom_lib_location_scala,
|
||||
"Print xspcomm-scala.jar location");
|
||||
app.add_flag("--show_xcom_lib_location_python",
|
||||
main_opts.show_xcom_lib_location_python,
|
||||
app.add_flag("--show_xcom_lib_location_python", main_opts.show_xcom_lib_location_python,
|
||||
"Print python module xspcomm location");
|
||||
app.add_flag("--show_xcom_lib_location_golang",
|
||||
main_opts.show_xcom_lib_location_golang,
|
||||
app.add_flag("--show_xcom_lib_location_golang", main_opts.show_xcom_lib_location_golang,
|
||||
"Print golang module xspcomm location");
|
||||
app.add_flag("--check", main_opts.check,
|
||||
"check install location and supproted languages");
|
||||
app.add_flag("--check", main_opts.check, "check install location and supproted languages");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -204,8 +173,7 @@ int main(int argc, char **argv)
|
|||
// handel main options here
|
||||
// if need version, print version
|
||||
if (main_opts.version) {
|
||||
PK_MESSAGE("version: %s-%s-%s%s", PROJECT_VERSION, GIT_BRANCH, GIT_HASH,
|
||||
GIT_DIRTY);
|
||||
PK_MESSAGE("version: %s-%s-%s%s", PROJECT_VERSION, GIT_BRANCH, GIT_HASH, GIT_DIRTY);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
@ -244,8 +212,7 @@ int main(int argc, char **argv)
|
|||
exit(0);
|
||||
}
|
||||
if (main_opts.show_xcom_lib_location_java) {
|
||||
auto java_location =
|
||||
picker::get_xcomm_lib("java/xspcomm-java.jar", erro_message);
|
||||
auto java_location = picker::get_xcomm_lib("java/xspcomm-java.jar", erro_message);
|
||||
if (java_location.size() == 0) {
|
||||
PK_ERROR("%s", erro_message.c_str());
|
||||
exit(1);
|
||||
|
@ -254,8 +221,7 @@ int main(int argc, char **argv)
|
|||
exit(0);
|
||||
}
|
||||
if (main_opts.show_xcom_lib_location_scala) {
|
||||
auto scala_location =
|
||||
picker::get_xcomm_lib("java/xspcomm-scala.jar", erro_message);
|
||||
auto scala_location = picker::get_xcomm_lib("java/xspcomm-scala.jar", erro_message);
|
||||
if (scala_location.size() == 0) {
|
||||
PK_ERROR("%s", erro_message.c_str());
|
||||
exit(1);
|
||||
|
@ -282,46 +248,36 @@ int main(int argc, char **argv)
|
|||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
int lang_index = 0;
|
||||
const char *check_libs[] = {"include", "java/xspcomm-java.jar",
|
||||
"scala/xspcomm-scala.jar", "python", "golang"};
|
||||
const char *check_libs[] = {"include", "java/xspcomm-java.jar", "scala/xspcomm-scala.jar", "python", "golang"};
|
||||
const char *check_langs[] = {"Cpp", "Java", "Scala", "Python", "Golang"};
|
||||
std::map<std::string, int> lang_map = {
|
||||
{"cpp", 0}, {"java", 1}, {"scala", 2}, {"python", 3}, {"golang", 4}};
|
||||
std::map<std::string, int> lang_map = {{"cpp", 0}, {"java", 1}, {"scala", 2}, {"python", 3}, {"golang", 4}};
|
||||
if (main_opts.check) {
|
||||
PK_MESSAGE("[OK ] Version: %s-%s-%s%s", PROJECT_VERSION, GIT_BRANCH,
|
||||
GIT_HASH, GIT_DIRTY);
|
||||
PK_MESSAGE("[OK ] Version: %s-%s-%s%s", PROJECT_VERSION, GIT_BRANCH, GIT_HASH, GIT_DIRTY);
|
||||
PK_MESSAGE("[OK ] Exec path: %s", picker::get_executable_path().c_str());
|
||||
auto temp_path = picker::get_template_path();
|
||||
if (temp_path.empty()) {
|
||||
PK_MESSAGE("[Err] Can't find default template path");
|
||||
} else {
|
||||
PK_MESSAGE("[OK ] Template path: %s", temp_path.c_str());
|
||||
|
||||
}
|
||||
int i = 0;
|
||||
for (auto lang : check_langs) {
|
||||
auto lib_location =
|
||||
picker::get_xcomm_lib(check_libs[i], erro_message);
|
||||
auto lib_location = picker::get_xcomm_lib(check_libs[i], erro_message);
|
||||
if (lib_location.size() == 0) {
|
||||
PK_ERROR("[Err] Support %6s (find: '%s' fail)", lang,
|
||||
check_libs[i]);
|
||||
PK_ERROR("[Err] Support %6s (find: '%s' fail)", lang, check_libs[i]);
|
||||
} else {
|
||||
PK_MESSAGE("[OK ] Support %6s (find: '%s' success)", lang,
|
||||
lib_location.c_str());
|
||||
PK_MESSAGE("[OK ] Support %6s (find: '%s' success)", lang, lib_location.c_str());
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
if (export_opts.language.size() != 0) {
|
||||
lang_index = lang_map[export_opts.language];
|
||||
auto lib_location =
|
||||
picker::get_xcomm_lib(check_libs[lang_index], erro_message);
|
||||
lang_index = lang_map[export_opts.language];
|
||||
auto lib_location = picker::get_xcomm_lib(check_libs[lang_index], erro_message);
|
||||
if (lib_location.size() == 0) {
|
||||
PK_ERROR("[Err] Support %6s (find: '%s' fail)",
|
||||
check_langs[lang_index], check_libs[lang_index]);
|
||||
PK_ERROR("[Err] Support %6s (find: '%s' fail)", check_langs[lang_index], check_libs[lang_index]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -341,24 +297,16 @@ int main(int argc, char **argv)
|
|||
picker::parser::sv(export_opts, sv_module_result);
|
||||
picker::parser::internal(export_opts, internal_sginal_result);
|
||||
|
||||
auto sv_pin_result = picker::codegen::lib(export_opts, sv_module_result, internal_sginal_result,
|
||||
signal_tree_json);
|
||||
auto sv_pin_result =
|
||||
picker::codegen::lib(export_opts, sv_module_result, internal_sginal_result, signal_tree_json);
|
||||
|
||||
std::map<std::string,
|
||||
std::function<void(picker::export_opts &,
|
||||
std::vector<picker::sv_signal_define>,
|
||||
std::vector<picker::sv_signal_define>,
|
||||
nlohmann::json &
|
||||
)>> func_map = {
|
||||
{"cpp", picker::codegen::cpp},
|
||||
{"python", picker::codegen::python},
|
||||
{"java", picker::codegen::java},
|
||||
{"scala", picker::codegen::scala},
|
||||
{"golang", picker::codegen::golang},
|
||||
std::map<std::string, std::function<void(picker::export_opts &, std::vector<picker::sv_signal_define>,
|
||||
std::vector<picker::sv_signal_define>, nlohmann::json &)>>
|
||||
func_map = {
|
||||
{"cpp", picker::codegen::cpp}, {"python", picker::codegen::python}, {"java", picker::codegen::java},
|
||||
{"scala", picker::codegen::scala}, {"golang", picker::codegen::golang},
|
||||
};
|
||||
func_map[export_opts.language](export_opts, sv_pin_result,
|
||||
internal_sginal_result,
|
||||
signal_tree_json);
|
||||
func_map[export_opts.language](export_opts, sv_pin_result, internal_sginal_result, signal_tree_json);
|
||||
// build the result with make
|
||||
if (export_opts.autobuild) {
|
||||
const std::string cmd = "cd " + export_opts.target_dir + " && make";
|
||||
|
@ -382,8 +330,7 @@ int main(int argc, char **argv)
|
|||
uvm_transaction.name = pack_opts.rename[i];
|
||||
i++;
|
||||
}
|
||||
picker::codegen::gen_uvm_param(pack_opts, uvm_transaction,
|
||||
filename);
|
||||
picker::codegen::gen_uvm_param(pack_opts, uvm_transaction, filename);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
int main()
|
||||
{
|
||||
std::string internal_pin_filename = "../example/Cache/Cache.yaml";
|
||||
std::string internal_pin_filename = "../example/Cache/Cache.yaml";
|
||||
std::vector<picker::sv_signal_define> pin_list = picker::parser::internal(internal_pin_filename);
|
||||
for (auto pin : pin_list) {
|
||||
std::cout << pin.logic_pin << " " << pin.logic_pin_type << " " << pin.logic_pin_hb << " " << pin.logic_pin_lb << std::endl;
|
||||
std::cout << pin.logic_pin << " " << pin.logic_pin_type << " " << pin.logic_pin_hb << " " << pin.logic_pin_lb
|
||||
<< std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -5,8 +5,8 @@ int main(int argc, char **argv)
|
|||
{
|
||||
auto ctx = std::map<std::string, std::string>{
|
||||
{"dut_name", "dut"},
|
||||
{"mode_name","test_name"},
|
||||
{"body","<this is body>"},
|
||||
{"mode_name", "test_name"},
|
||||
{"body", "<this is body>"},
|
||||
};
|
||||
PK_MESSAGE("render result:\n%s", picker::template_rander("template/python/pybind11.cpp", ctx).c_str());
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue