diff --git a/Makefile b/Makefile index 7a168e3..73fab62 100644 --- a/Makefile +++ b/Makefile @@ -21,13 +21,17 @@ all: autotest bit2txt draw_svg_tiles new_fp fp2bit hstrrep sort_seq merge_seq autotest: autotest.o $(MODEL_OBJ) floorplan.o control.o helper.o model.h +autotest.c: model.h floorplan.h control.h + new_fp: new_fp.o $(MODEL_OBJ) floorplan.o helper.o new_fp.o: new_fp.c floorplan.h model.h helper.h -fp2bit: fp2bit.c $(MODEL_OBJ) bits.o helper.o +fp2bit: fp2bit.o $(MODEL_OBJ) floorplan.o control.o bits.o helper.o -floorplan.o: floorplan.c floorplan.h model.h +fp2bit.o: fp2bit.c model.h floorplan.h bits.h helper.h + +floorplan.o: floorplan.c floorplan.h model.h control.h bits.o: bits.c bits.h model.h diff --git a/README b/README index 2b0d594..52bd2e8 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ Design Principles - plain C, no C++ - simple Makefiles - text-based file formats -- no documentation - read the sources +- no documentation - please read the sources - automatic test suite Libraries diff --git a/autotest.c b/autotest.c index af6ffe0..ce975e3 100644 --- a/autotest.c +++ b/autotest.c @@ -85,7 +85,13 @@ int main(int argc, char** argv) dev->iob.slew = SLEW_SLOW; dev->iob.suspend = SUSP_3STATE; - // todo: configure logic + // configure logic + dev = fpga_dev(&model, /*y*/ 68, /*x*/ 13, DEV_LOGIC, /*LOGIC_X*/ 1); + EXIT(!dev); + dev->instantiated = 1; + dev->logic.D_used = 1; + rc = fpga_set_lut(&model, dev, D6_LUT, "A3", ZTERM); + EXIT(rc); mkdir(AUTOTEST_TMP_DIR, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); dest_f = fopen(AUTOTEST_TMP_DIR "/test_0001.fp", "w"); diff --git a/bits.c b/bits.c index 42d8d6b..89a18c5 100644 --- a/bits.c +++ b/bits.c @@ -7,3 +7,8 @@ #include "model.h" #include "bits.h" + +int write_bits(FILE* f, struct fpga_model* model) +{ + return 0; +} diff --git a/bits.h b/bits.h index 0d6562e..658210e 100644 --- a/bits.h +++ b/bits.h @@ -4,3 +4,5 @@ // This is free and unencumbered software released into the public domain. // For details see the UNLICENSE file at the root of the source tree. // + +int write_bits(FILE* f, struct fpga_model* model); diff --git a/control.c b/control.c index ea5595f..1c5b7d9 100644 --- a/control.c +++ b/control.c @@ -156,6 +156,50 @@ int fpga_find_iob(struct fpga_model* model, const char* sitename, return -1; } +const char* fpga_iob_sitename(struct fpga_model* model, int y, int x, + int idx) +{ + int i; + + if (y == TOP_OUTER_ROW) { + for (i = 0; i < sizeof(xc6slx9_iob_top)/sizeof(xc6slx9_iob_top[0]); i++) { + if (xc6slx9_iob_right[i].xy == x) { + if (idx < 0 || idx > 3) return 0; + return xc6slx9_iob_top[i].name[idx]; + } + } + return 0; + } + if (y == model->y_height-BOT_OUTER_ROW) { + for (i = 0; i < sizeof(xc6slx9_iob_bottom)/sizeof(xc6slx9_iob_bottom[0]); i++) { + if (xc6slx9_iob_bottom[i].xy == x) { + if (idx < 0 || idx > 3) return 0; + return xc6slx9_iob_bottom[i].name[idx]; + } + } + return 0; + } + if (x == LEFT_OUTER_COL) { + for (i = 0; i < sizeof(xc6slx9_iob_left)/sizeof(xc6slx9_iob_left[0]); i++) { + if (xc6slx9_iob_left[i].xy == y) { + if (idx < 0 || idx > 1) return 0; + return xc6slx9_iob_left[i].name[idx]; + } + } + return 0; + } + if (x == model->x_width-RIGHT_OUTER_O) { + for (i = 0; i < sizeof(xc6slx9_iob_right)/sizeof(xc6slx9_iob_right[0]); i++) { + if (xc6slx9_iob_right[i].xy == y) { + if (idx < 0 || idx > 1) return 0; + return xc6slx9_iob_right[i].name[idx]; + } + } + return 0; + } + return 0; +} + struct fpga_device* fpga_dev(struct fpga_model* model, int y, int x, enum fpgadev_type type, int idx) { @@ -173,3 +217,32 @@ struct fpga_device* fpga_dev(struct fpga_model* model, } return 0; } + +#define MAX_LUT_LEN 512 + +int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev, + int which_lut, const char* lut_str, int lut_len) +{ + char** ptr; + + if (dev->type != DEV_LOGIC) + return -1; + switch (which_lut) { + case A6_LUT: ptr = &dev->logic.A6_lut; break; + case B6_LUT: ptr = &dev->logic.B6_lut; break; + case C6_LUT: ptr = &dev->logic.C6_lut; break; + case D6_LUT: ptr = &dev->logic.D6_lut; break; + default: return -1; + } + if (!(*ptr)) { + *ptr = malloc(MAX_LUT_LEN); + if (!(*ptr)) { + OUT_OF_MEM(); + return -1; + } + } + if (lut_len == ZTERM) lut_len = strlen(lut_str); + memcpy(*ptr, lut_str, lut_len); + (*ptr)[lut_len] = 0; + return 0; +} diff --git a/control.h b/control.h index 8cfd597..fa3f22c 100644 --- a/control.h +++ b/control.h @@ -8,5 +8,13 @@ int fpga_find_iob(struct fpga_model* model, const char* sitename, int* y, int* x, int* idx); +const char* fpga_iob_sitename(struct fpga_model* model, int y, int x, + int idx); + struct fpga_device* fpga_dev(struct fpga_model* model, int y, int x, enum fpgadev_type type, int idx); + +enum { A6_LUT, B6_LUT, C6_LUT, D6_LUT }; +// lut_len can be -1 (ZTERM) +int fpga_set_lut(struct fpga_model* model, struct fpga_device* dev, + int which_lut, const char* lut_str, int lut_len); diff --git a/floorplan.c b/floorplan.c index fd4b82a..e2d7404 100644 --- a/floorplan.c +++ b/floorplan.c @@ -8,6 +8,7 @@ #include #include "model.h" +#include "control.h" #include "floorplan.h" void printf_version(FILE* f) @@ -146,7 +147,7 @@ static int printf_IOB(FILE* f, struct fpga_model* model, case 0: break; default: EXIT(1); } if (tile->devs[i].iob.O_used) - printf_wrap(f, line, plen, "o_used"); + printf_wrap(f, line, plen, "O_used"); switch (tile->devs[i].iob.suspend) { case SUSP_LAST_VAL: printf_wrap(f, line, plen, "suspend DRIVE_LAST_VALUE"); @@ -204,6 +205,109 @@ static int printf_IOB(FILE* f, struct fpga_model* model, return 0; } +static int read_IOB_attr(struct fpga_model* model, struct fpga_device* dev, + const char* w1, int w1_len, const char* w2, int w2_len) +{ + // First the one-word attributes. + if (!str_cmp(w1, w1_len, "O_used", ZTERM)) { + dev->iob.O_used = 1; + goto inst_1; + } + // The remaining attributes all require 2 words. + if (w2_len < 1) return 0; + if (!str_cmp(w1, w1_len, "type", ZTERM)) + return 2; // no reason for instantiation + if (!str_cmp(w1, w1_len, "istd", ZTERM)) { + memcpy(dev->iob.istandard, w2, w2_len); + dev->iob.istandard[w2_len] = 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "ostd", ZTERM)) { + memcpy(dev->iob.ostandard, w2, w2_len); + dev->iob.ostandard[w2_len] = 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "bypass_mux", ZTERM)) { + if (!str_cmp(w2, w2_len, "I", ZTERM)) + dev->iob.bypass_mux = BYPASS_MUX_I; + else if (!str_cmp(w2, w2_len, "O", ZTERM)) + dev->iob.bypass_mux = BYPASS_MUX_O; + else if (!str_cmp(w2, w2_len, "T", ZTERM)) + dev->iob.bypass_mux = BYPASS_MUX_T; + else return 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "imux", ZTERM)) { + if (!str_cmp(w2, w2_len, "I_B", ZTERM)) + dev->iob.I_mux = IMUX_I_B; + else if (!str_cmp(w2, w2_len, "I", ZTERM)) + dev->iob.I_mux = IMUX_I; + else return 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "strength", ZTERM)) { + dev->iob.drive_strength = to_i(w2, w2_len); + goto inst_2; + } + if (!str_cmp(w1, w1_len, "slew", ZTERM)) { + if (!str_cmp(w2, w2_len, "SLOW", ZTERM)) + dev->iob.slew = SLEW_SLOW; + else if (!str_cmp(w2, w2_len, "FAST", ZTERM)) + dev->iob.slew = SLEW_FAST; + else if (!str_cmp(w2, w2_len, "QUIETIO", ZTERM)) + dev->iob.slew = SLEW_QUIETIO; + else return 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "suspend", 7)) { + if (!str_cmp(w2, w2_len, "DRIVE_LAST_VALUE", ZTERM)) + dev->iob.suspend = SUSP_LAST_VAL; + else if (!str_cmp(w2, w2_len, "3STATE", ZTERM)) + dev->iob.suspend = SUSP_3STATE; + else if (!str_cmp(w2, w2_len, "3STATE_PULLUP", ZTERM)) + dev->iob.suspend = SUSP_3STATE_PULLUP; + else if (!str_cmp(w2, w2_len, "3STATE_PULLDOWN", ZTERM)) + dev->iob.suspend = SUSP_3STATE_PULLDOWN; + else if (!str_cmp(w2, w2_len, "3STATE_KEEPER", ZTERM)) + dev->iob.suspend = SUSP_3STATE_KEEPER; + else if (!str_cmp(w2, w2_len, "3STATE_OCT_ON", ZTERM)) + dev->iob.suspend = SUSP_3STATE_OCT_ON; + else return 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "in_term", ZTERM)) { + if (!str_cmp(w2, w2_len, "NONE", ZTERM)) + dev->iob.in_term = ITERM_NONE; + else if (!str_cmp(w2, w2_len, "UNTUNED_SPLIT_25", ZTERM)) + dev->iob.in_term = ITERM_UNTUNED_25; + else if (!str_cmp(w2, w2_len, "UNTUNED_SPLIT_50", ZTERM)) + dev->iob.in_term = ITERM_UNTUNED_50; + else if (!str_cmp(w2, w2_len, "UNTUNED_SPLIT_75", ZTERM)) + dev->iob.in_term = ITERM_UNTUNED_75; + else return 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "out_term", ZTERM)) { + if (!str_cmp(w2, w2_len, "NONE", ZTERM)) + dev->iob.out_term = OTERM_NONE; + else if (!str_cmp(w2, w2_len, "UNTUNED_25", ZTERM)) + dev->iob.out_term = OTERM_UNTUNED_25; + else if (!str_cmp(w2, w2_len, "UNTUNED_50", ZTERM)) + dev->iob.out_term = OTERM_UNTUNED_50; + else if (!str_cmp(w2, w2_len, "UNTUNED_75", ZTERM)) + dev->iob.out_term = OTERM_UNTUNED_75; + else return 0; + goto inst_2; + } + return 0; +inst_1: + dev->instantiated = 1; + return 1; +inst_2: + dev->instantiated = 2; + return 2; +} + static int printf_LOGIC(FILE* f, struct fpga_model* model, int y, int x, int config_only) { @@ -237,12 +341,85 @@ static int printf_LOGIC(FILE* f, struct fpga_model* model, break; default: EXIT(1); } + if (tile->devs[i].logic.A_used) + printf_wrap(f, line, plen, "A_used"); + if (tile->devs[i].logic.B_used) + printf_wrap(f, line, plen, "B_used"); + if (tile->devs[i].logic.C_used) + printf_wrap(f, line, plen, "C_used"); + if (tile->devs[i].logic.D_used) + printf_wrap(f, line, plen, "D_used"); + if (tile->devs[i].logic.A6_lut && tile->devs[i].logic.A6_lut[0]) + printf_wrap(f, line, plen, "A6_lut %s", + tile->devs[i].logic.A6_lut); + if (tile->devs[i].logic.B6_lut && tile->devs[i].logic.B6_lut[0]) + printf_wrap(f, line, plen, "B6_lut %s", + tile->devs[i].logic.B6_lut); + if (tile->devs[i].logic.C6_lut && tile->devs[i].logic.C6_lut[0]) + printf_wrap(f, line, plen, "C6_lut %s", + tile->devs[i].logic.C6_lut); + if (tile->devs[i].logic.D6_lut && tile->devs[i].logic.D6_lut[0]) + printf_wrap(f, line, plen, "D6_lut %s", + tile->devs[i].logic.D6_lut); strcat(line, "\n"); fprintf(f, line); } return 0; } +static int read_LOGIC_attr(struct fpga_model* model, struct fpga_device* dev, + const char* w1, int w1_len, const char* w2, int w2_len) +{ + // First the one-word attributes. + if (!str_cmp(w1, w1_len, "A_used", ZTERM)) { + dev->logic.A_used = 1; + goto inst_1; + } + if (!str_cmp(w1, w1_len, "B_used", ZTERM)) { + dev->logic.B_used = 1; + goto inst_1; + } + if (!str_cmp(w1, w1_len, "C_used", ZTERM)) { + dev->logic.C_used = 1; + goto inst_1; + } + if (!str_cmp(w1, w1_len, "D_used", ZTERM)) { + dev->logic.D_used = 1; + goto inst_1; + } + // The remaining attributes all require 2 words. + if (w2_len < 1) return 0; + if (!str_cmp(w1, w1_len, "type", ZTERM)) + return 2; // no reason for instantiation + if (!str_cmp(w1, w1_len, "A6_lut", ZTERM)) { + if (fpga_set_lut(model, dev, A6_LUT, w2, w2_len)) + return 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "B6_lut", ZTERM)) { + if (fpga_set_lut(model, dev, B6_LUT, w2, w2_len)) + return 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "C6_lut", ZTERM)) { + if (fpga_set_lut(model, dev, C6_LUT, w2, w2_len)) + return 0; + goto inst_2; + } + if (!str_cmp(w1, w1_len, "D6_lut", ZTERM)) { + if (fpga_set_lut(model, dev, D6_LUT, w2, w2_len)) + return 0; + goto inst_2; + } + return 0; +inst_1: + dev->instantiated = 1; + return 1; +inst_2: + dev->instantiated = 2; + return 2; +} + int printf_devices(FILE* f, struct fpga_model* model, int config_only) { int x, y, i, rc; @@ -332,6 +509,7 @@ int printf_devices(FILE* f, struct fpga_model* model, int config_only) break; case DEV_IOB: case DEV_LOGIC: + case DEV_NONE: // to suppress compiler warning break; } @@ -483,3 +661,99 @@ int printf_switches(FILE* f, struct fpga_model* model, int enabled_only) } return 0; } + +static enum fpgadev_type to_type(const char* s, int len) +{ + if (!str_cmp(s, len, "IOB", 3)) return DEV_IOB; + if (!str_cmp(s, len, "LOGIC", 5)) return DEV_LOGIC; + return DEV_NONE; +} + +int read_floorplan(struct fpga_model* model, FILE* f) +{ + char line[1024]; + int beg, end; + + while (fgets(line, sizeof(line), f)) { + next_word(line, 0, &beg, &end); + if (end == beg) continue; + + if (!str_cmp(&line[beg], end-beg, "dev", 3)) { + int y_beg, y_end, x_beg, x_end; + int y_coord, x_coord; + int type_beg, type_end, idx_beg, idx_end; + enum fpgadev_type dev_type; + int dev_idx, words_consumed; + struct fpga_device* dev_ptr; + int next_beg, next_end, second_beg, second_end; + + next_word(line, end, &y_beg, &y_end); + next_word(line, y_end, &x_beg, &x_end); + if (y_end < y_beg+2 || x_end < x_beg+2 + || line[y_beg] != 'y' || line[x_beg] != 'x' + || !all_digits(&line[y_beg+1], y_end-y_beg-1) + || !all_digits(&line[x_beg+1], x_end-x_beg-1)) { + fprintf(stderr, "error %i: %s", __LINE__, line); + continue; + } + y_coord = to_i(&line[y_beg+1], y_end-y_beg-1); + x_coord = to_i(&line[x_beg+1], x_end-x_beg-1); + + next_word(line, x_end, &type_beg, &type_end); + next_word(line, type_end, &idx_beg, &idx_end); + + if (type_end == type_beg || idx_end == idx_beg + || !all_digits(&line[idx_beg], idx_end-idx_beg)) { + fprintf(stderr, "error %i: %s", __LINE__, line); + continue; + } + dev_type = to_type(&line[type_beg], type_end-type_beg); + dev_idx = to_i(&line[idx_beg], idx_end-idx_beg); + dev_ptr = fpga_dev(model, y_coord, x_coord, dev_type, dev_idx); + if (!dev_ptr) { + fprintf(stderr, "error %i: %s", __LINE__, line); + continue; + } + + next_end = idx_end; + while (next_word(line, next_end, &next_beg, &next_end), + next_end > next_beg) { + next_word(line, next_end, &second_beg, &second_end); + switch (dev_type) { + case DEV_IOB: + words_consumed = read_IOB_attr( + model, dev_ptr, + &line[next_beg], + next_end-next_beg, + &line[second_beg], + second_end-second_beg); + break; + case DEV_LOGIC: + words_consumed = read_LOGIC_attr( + model, dev_ptr, + &line[next_beg], + next_end-next_beg, + &line[second_beg], + second_end-second_beg); + break; + default: + fprintf(stderr, "error %i: %s", + __LINE__, line); + goto next_line; + } + if (!words_consumed) + fprintf(stderr, + "error %i w1 %.*s w2 %.*s: %s", + __LINE__, next_end-next_beg, + &line[next_beg], + second_end-second_beg, + &line[second_beg], + line); + else if (words_consumed == 2) + next_end = second_end; + } +next_line: ; + } + } + return 0; +} diff --git a/floorplan.h b/floorplan.h index 439be5b..e88500e 100644 --- a/floorplan.h +++ b/floorplan.h @@ -24,6 +24,8 @@ // - lines should typically not exceed 80 characters // +int read_floorplan(struct fpga_model* model, FILE* f); + void printf_version(FILE* f); int printf_tiles(FILE* f, struct fpga_model* model); int printf_devices(FILE* f, struct fpga_model* model, int config_only); diff --git a/fp2bit.c b/fp2bit.c index 0002ebe..3caea7d 100644 --- a/fp2bit.c +++ b/fp2bit.c @@ -6,17 +6,45 @@ // #include "model.h" +#include "floorplan.h" #include "bits.h" int main(int argc, char** argv) { struct fpga_model model; - int rc; + FILE* fp, *fbits; + int rc = -1; + + if (argc != 3) { + fprintf(stderr, + "\n" + "%s - floorplan to bitstream\n" + "Usage: %s \n" + "\n", argv[0], argv[0]); + goto fail; + } + + if (!strcmp(argv[1], "-")) + fp = stdin; + else { + fp = fopen(argv[1], "r"); + if (!fp) { + fprintf(stderr, "Error opening %s.\n", argv[1]); + goto fail; + } + } + fbits = fopen(argv[2], "w"); + if (!fbits) { + fprintf(stderr, "Error opening %s.\n", argv[2]); + goto fail; + } if ((rc = fpga_build_model(&model, XC6SLX9_ROWS, XC6SLX9_COLUMNS, XC6SLX9_LEFT_WIRING, XC6SLX9_RIGHT_WIRING))) goto fail; + if ((rc = read_floorplan(&model, fp))) goto fail; + if ((rc = write_bits(fbits, &model))) goto fail; return EXIT_SUCCESS; fail: return rc; diff --git a/helper.c b/helper.c index c5741bc..aa30579 100644 --- a/helper.c +++ b/helper.c @@ -702,6 +702,47 @@ void next_word(const char*s, int start, int* beg, int* end) *end = i; } +int str_cmp(const char* a, int a_len, const char* b, int b_len) +{ + int i = 0; + + if (a_len == -1) { + a_len = 0; + while (a[a_len]) a_len++; + } + if (b_len == -1) { + b_len = 0; + while (b[b_len]) b_len++; + } + while (1) { + if (i >= a_len) { + if (i >= b_len) + return 0; + return -1; + } + if (i >= b_len) { + if (i >= a_len) + return 0; + return 1; + } + if (a[i] != b[i]) + return a[i] - b[i]; + i++; + } +} + +int all_digits(const char* a, int len) +{ + int i; + + if (!len) return 0; + for (i = 0; i < len; i++) { + if (a[i] < '0' || a[i] > '9') + return 0; + } + return 1; +} + int to_i(const char* s, int len) { int num, base; diff --git a/helper.h b/helper.h index f5abb01..8d7fbaa 100644 --- a/helper.h +++ b/helper.h @@ -16,6 +16,8 @@ #define PROGRAM_REVISION "2012-06-27" #define MACRO_STR(arg) #arg +#define OUT_OF_MEM() { fprintf(stderr, \ + "Out of memory in %s:%i\n", __FILE__, __LINE__); } #define EXIT(expr) if (expr) { fprintf(stderr, \ "Internal error in %s:%i\n", __FILE__, __LINE__); exit(1); } @@ -77,7 +79,13 @@ uint64_t read_lut64(uint8_t* two_minors, int off_in_frame); int get_vm_mb(void); int get_random(void); int compare_with_number(const char* a, const char* b); +// If no next word is found, *end == *beg void next_word(const char* s, int start, int* beg, int* end); +// if a_len or b_len are -1, the length is until 0-termination +#define ZTERM -1 +int str_cmp(const char* a, int a_len, const char* b, int b_len); +// all_digits() returns 0 if len == 0 +int all_digits(const char* a, int len); int to_i(const char* s, int len); uint32_t hash_djb2(const unsigned char* str); diff --git a/model.h b/model.h index faa0414..9049197 100644 --- a/model.h +++ b/model.h @@ -168,7 +168,7 @@ enum fpga_tile_type #define CENTER_LOGIC_O 2 #define CENTER_ROUTING_O 3 -#define YX_TILE(model, y, x) (&(model)->tiles[(y)*model->x_width+(x)]) +#define YX_TILE(model, y, x) (&(model)->tiles[(y)*(model)->x_width+(x)]) // tile flags @@ -271,6 +271,8 @@ const char* logicin_s(int wire, int routing_io); enum fpgadev_type { + DEV_NONE = 0, + DEV_LOGIC, DEV_TIEOFF, DEV_MACC, diff --git a/model_devices.c b/model_devices.c index 05a6832..0ce5bdb 100644 --- a/model_devices.c +++ b/model_devices.c @@ -325,13 +325,14 @@ int init_devices(struct fpga_model* model) if (!is_atx(X_LOGIC_COL, model, x)) continue; for (y = TOP_IO_TILES; y < model->y_height - BOT_IO_TILES; y++) { + // M and L are at index 0, X is at index 1. if (YX_TILE(model, y, x)->flags & TF_LOGIC_XM_DEV) { - if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_X))) goto fail; if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_M))) goto fail; + if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_X))) goto fail; } if (YX_TILE(model, y, x)->flags & TF_LOGIC_XL_DEV) { - if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_X))) goto fail; if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_L))) goto fail; + if ((rc = add_dev(model, y, x, DEV_LOGIC, LOGIC_X))) goto fail; } } } diff --git a/sort_seq.c b/sort_seq.c index 12be30a..49514fa 100644 --- a/sort_seq.c +++ b/sort_seq.c @@ -106,27 +106,6 @@ static void find_number(const char* s, int s_len, int* num_start, int* num_end) } } -static int str_cmp(const char* a, int a_len, const char* b, int b_len) -{ - int i = 0; - - while (1) { - if (i >= a_len) { - if (i >= b_len) - return 0; - return -1; - } - if (i >= b_len) { - if (i >= a_len) - return 0; - return 1; - } - if (a[i] != b[i]) - return a[i] - b[i]; - i++; - } -} - static int is_known_suffix(const char* str, int str_len) { int i;