OpenFPGA/libs/EXTERNAL/libsdcparse/src/main.cpp

257 lines
7.2 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "sdcparse.hpp"
using namespace sdcparse;
void print_string_group(const StringGroup& group);
void print_from_to_group(const StringGroup& from, const StringGroup& to);
class PrintCallback : public Callback {
public:
//Start of parsing
void start_parse() override { }
//Sets current filename
void filename(std::string fname) override { filename_ = fname; }
//Sets current line number
void lineno(int line_num) override { lineno_ = line_num; }
void create_clock(const CreateClock& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
printf("create_clock -period %f -waveform {%f %f} ",
cmd.period,
cmd.rise_edge,
cmd.fall_edge);
if(cmd.is_virtual) {
printf("-name %s",
cmd.name.c_str());
} else {
print_string_group(cmd.targets);
}
printf("\n");
}
void set_io_delay(const SetIoDelay& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
if(cmd.type == IoDelayType::INPUT) {
printf("set_input_delay");
} else {
printf("set_output_delay");
}
printf(" -clock %s", cmd.clock_name.c_str());
if (cmd.is_max) {
printf(" -max");
}
if (cmd.is_min) {
printf(" -min");
}
printf(" %f ", cmd.delay);
print_string_group(cmd.target_ports);
printf("\n");
}
void set_clock_groups(const SetClockGroups& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
printf("set_clock_groups");
if(cmd.type == ClockGroupsType::EXCLUSIVE) {
printf(" -exclusive");
}
for(const auto& clk_grp : cmd.clock_groups) {
printf(" -group ");
print_string_group(clk_grp);
}
printf("\n");
}
void set_false_path(const SetFalsePath& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
printf("set_false_path ");
print_from_to_group(cmd.from, cmd.to);
printf("\n");
}
void set_min_max_delay(const SetMinMaxDelay& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
if(cmd.type == MinMaxType::MAX) {
printf("set_max_delay");
} else {
printf("set_min_delay");
}
printf(" %f ", cmd.value);
print_from_to_group(cmd.from, cmd.to);
printf("\n");
}
void set_multicycle_path(const SetMulticyclePath& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
printf("set_multicycle_path %d ", cmd.mcp_value);
if(cmd.is_setup) {
printf("-setup ");
}
if(cmd.is_hold) {
printf("-hold ");
}
print_from_to_group(cmd.from, cmd.to);
printf("\n");
}
void set_clock_uncertainty(const SetClockUncertainty& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
printf("set_clock_uncertainty ");
if(cmd.is_setup) {
printf("-setup ");
}
if(cmd.is_hold) {
printf("-hold ");
}
print_from_to_group(cmd.from, cmd.to);
printf(" %f ", cmd.value);
printf("\n");
}
void set_clock_latency(const SetClockLatency& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
printf("set_clock_latency ");
if(cmd.type == ClockLatencyType::SOURCE) {
printf("-source ");
}
if(cmd.is_early) {
printf("-early ");
}
if(cmd.is_late) {
printf("-late ");
}
printf("%f ", cmd.value);
print_string_group(cmd.target_clocks);
printf("\n");
}
void set_disable_timing(const SetDisableTiming& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
printf("set_disable_timing ");
print_from_to_group(cmd.from, cmd.to);
printf("\n");
}
void set_timing_derate(const SetTimingDerate& cmd) override {
printf("#%s:%d\n", filename_.c_str(), lineno_);
printf("set_timing_derate ");
if(cmd.is_early) {
printf("-early ");
}
if(cmd.is_late) {
printf("-late ");
}
if(cmd.derate_nets) {
printf("-net_delay ");
}
if(cmd.derate_cells) {
printf("-cell_delay ");
}
printf("%f ", cmd.value);
print_string_group(cmd.cell_targets);
printf("\n");
}
//End of parsing
void finish_parse() override { }
//Error during parsing
void parse_error(const int curr_lineno, const std::string& near_text, const std::string& msg) override {
fprintf(stderr, "Custom Error");
if(curr_lineno > 0) {
fprintf(stderr, " at line %d", curr_lineno);
}
if(near_text != "") {
if(near_text == "\n") {
fprintf(stderr, " near '\\n'");
} else if(near_text == "\n\r") {
fprintf(stderr, " near '\\n\\r'");
} else {
fprintf(stderr, " near '%s'", near_text.c_str());
}
}
fprintf(stderr, ": %s\n", msg.c_str());
error_ = true;
}
bool error() { return error_; }
private:
std::string filename_ = "";
int lineno_ = 0;
bool error_ = false;
};
int main(int argc, char **argv) {
if(argc != 2) {
fprintf(stderr, "Usage: %s filename.sdc\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "Reads in an SDC file into internal data structures\n");
fprintf(stderr, "and then prints it out\n");
exit(1);
}
PrintCallback callback;
sdc_parse_filename(argv[1], callback);
if(callback.error()) {
return 1;
}
return 0;
}
void print_string_group(const StringGroup& group) {
const char *start_token, *end_token;
if(group.type == StringGroupType::STRING) {
start_token = "{";
end_token = "}";
} else if (group.type == StringGroupType::CLOCK) {
start_token = "[get_clocks {";
end_token = "}]";
} else if (group.type == StringGroupType::PORT) {
start_token = "[get_ports {";
end_token = "}]";
} else if (group.type == StringGroupType::CELL) {
start_token = "[get_cells {";
end_token = "}]";
} else if (group.type == StringGroupType::PIN) {
start_token = "[get_pins {";
end_token = "}]";
} else {
printf("Unsupported sdc string group type\n");
exit(1);
}
if(!group.strings.empty()) {
printf("%s", start_token);
for(size_t i = 0; i < group.strings.size(); ++i) {
printf("%s", group.strings[i].c_str());
if(i != group.strings.size() - 1) {
printf(" ");
}
}
printf("%s", end_token);
}
}
void print_from_to_group(const StringGroup& from, const StringGroup& to) {
if(!from.strings.empty()) {
printf("-from ");
print_string_group(from);
}
if(!to.strings.empty()) {
printf(" -to ");
print_string_group(to);
}
}