#include #include #include #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); } }