// // Модуль: утилита преобразования списка цепей PCAD-200x // в исходный текст на Verolog HDL // // Компилятор: Microsoft Visual C++ 2005 // Разработчик: 1801BM1@gmail.com // // #include "vnet32.h" // // Буфера для обработки строки // BYTE Line[FL_LINSIZE+4]; BYTE Token[FL_LINSIZE+4]; DWORD ir_prod_l[PRO_MAX]; DWORD ir_prod_h[PRO_MAX]; DWORD mr_prod_l[PRO_MAX]; DWORD mr_prod_h[PRO_MAX]; int nodecomp; int pline; int dline; int ncomp = 0; int nnode = 0; int nnet = 0; DWORD nline; PFHANDLE Input = NULL; PFHANDLE Output = NULL; CMP cmp[CMP_MAX]; NET net[NET_MAX]; TYP typ[] = { {"370",{ NULL, "y2", NULL, NULL, "x5", NULL, "+", NULL, NULL, "+" }}, {"371",{ "x1", NULL, "y3", "y4", NULL, "x6", NULL, "+", "+", NULL }}, {"372",{ "x1", "y2", "y3", "y4", "x5", "x6", "+", "+", "+", "+" }}, {"373",{ "x1", NULL, "x3", "y4", NULL, "+", NULL, "+", "+", NULL }}, {"374",{ "x1", "x2", "x3", "y4", NULL, "+", "+", "y8", "+", NULL }}, {"375",{ "x1", "y2", "y3", "x4", "x5", "x6", "+", "+", "y9", "+" }}, {"376",{ "x1", NULL, "x3", "y4", NULL, "x6", NULL, "x8", "y9", NULL }}, {"377",{ "x1", "y2", "x3", "y4", "x5", "x6", "+", "x8", "y9", "+" }}, {"378",{ "x1", "y2", "x3", NULL, "x5", "+", "+", "+", NULL, "+" }}, {"379",{ "x1", "y2", "x3", "y4", "x5", "x6", "+", "x8", "+", "+" }}, {"380",{ "x1", "y2", "y3", "x4", "x5", "x6", "+", "+", "+", "+" }}, {"381",{ "x1", "y2", "x3", "x4", NULL, "x6", "+", "+", "+", NULL }}, {"382",{ "x1", "y2", "x3", "x4", "x5", "x6", "+", "y8", "+", "+" }}, {"383",{ "x1", "y2", "x3", "x4", "x5", "x6", "+", "+", "+", "+" }}, {"384",{ "x1", NULL, "y3", NULL, "x5", NULL, NULL, "+", NULL, "+" }}, {"385",{ "x1", "x2", "y3", NULL, "x5", NULL, "+", "y8", NULL, "+" }}, {"386",{ "x1", "y2", "y3", "y4", "x5", "x6", "x7", "+", "+", "+" }}, {"387",{ "x1", "y2", "x3", "y4", "x5", "x6", "+", "+", "+", "+" }}, {"388",{ "x1", "y2", "x3", "y4", "y5", "x6", "x7", "+", "+", "x10"}}, {"389",{ "x1", "x2", "y3", "x4", "y5", "x6", "+", "+", "+", "x10"}}, {"390",{ "x1", NULL, NULL, "y4", "x5", "x6", NULL, NULL, "y9", "x10"}}, {"391",{ "x1", "x2", "y3", "y4", "x5", "x6", "+", "+", "y9", "x10"}}, {"392",{ "x1", NULL, "x3", "y4", "x5", NULL, NULL, "+", "+", "+" }}, {"393",{ "x1", NULL, "x3", "y4", "x5", "x6", NULL, "+", "y9", "+" }}, {"394",{ "x1", "y2", "x3", "y4", "x5", "x6", "+", "+", "y9", "x10"}}, {"395",{ "x1", "y2", "x3", "x4", "x5", "x6", "+", "y8", "+", "+" }}, {"396",{ "x1", "y2", "x3", "x4", "x5", "x6", "y7", "+", "+", "x10"}}, {"397",{ "x1", "y2", "x3", "x4", "x5", "x6", "y7", "y8", "+", "x10"}}, {"398",{ "x1", "y2", NULL, "x4", "x5", "x6", "+", NULL, "y9", "x10"}}, {"399",{ "r1", "x2", "q3", "q4", NULL, "s6", "y7", "+", "+", NULL }}, {"400",{ "x1", "y2", "y3", "x4", "x5", "x6", "x7", "+", "y9", "x10"}}, {"401",{ "x1", NULL, "x3", "y4", "x5", "x6", NULL, "x8", "y9", "x10"}}, {"402",{ "r1", NULL, "q3", "q4", NULL, "s6", NULL, "+", "+", NULL }}, {"403",{ "x1", "x2", "x3", "y4", "x5", "x6", "y7", "x8", "y9", "x10"}}, {"404",{ "c1", NULL, "q3", "q4", "r5", "+", NULL, "+", "+", "s10"}}, {"405",{ "c1", "x2", "q3", "q4", "r5", "+", "y7", "+", "+", "s10"}}, {"406",{ "c1", "r2", "q3", "q4", "r5", "+", "+", "+", "+", "s10"}}, {"407",{ "c1", "s2", "q3", "q4", "s5", "+", "+", "+", "+", "r10"}}, {"408",{ NULL, "q2", "q3", NULL, "r5", "+", NULL, NULL, NULL, "s10"}}, {"409",{ NULL, "q2", "q3", NULL, "r5", "+", "x7", "y8", NULL, "s10"}}, {"410",{ NULL, "q2", "q3", "s4", "r5", "+", NULL, NULL, "+", "s10"}}, {"411",{ "q1", NULL, "r3", "q4", "r5", "+", NULL, NULL, NULL, "s10"}}, {"412",{ NULL, "q2", "q3", "s4", "r5", "+", "x7", "y8", NULL, "s10"}}, {"413",{ "q1", NULL, "r3", "q4", "r5", "+", "x7", "y8", NULL, "s10"}}, {"414",{ "q1", NULL, NULL, "s4", "r5", "q6", NULL, NULL, "r9", "s10"}}, {"415",{ "q1", NULL, NULL, "s4", "r5", "q6", "x7", "y8", "r9", "s10"}}, {"416",{ "c1", NULL, "q3", "q4", "d5", "+", NULL, "+", "+", "+" }}, {"417",{ "x1", NULL, NULL, "y4", "x5", "x6", NULL, NULL, "+", "x10"}}, {"418",{ "x1", "x2", "y3", "y4", "x5", "x6", "+", "+", "+", "x10"}}, {"419",{ "x1", "y2", NULL, "x4", "x5", "x6", "+", NULL, "+", "x10"}}, {"420",{ "x1", "y2", "y3", "x4", "x5", "x6", "x7", "+", "+", "x10"}}, {"421",{ "x1", "y2", "x3", "x4", "x5", "x6", "+", "+", "+", "x10"}}, {"422",{ "x1", "y2", "x3", "x4", "x5", "x6", "x7", "y8", "+", "x10"}}, {"423",{ "x1", "y2", NULL, "x4", "x5", "x6", "+", NULL, "+", "+" }}, {"424",{ "x1", "y2", "y3", "x4", "x5", "x6", "x7", "+", "+", "+" }}, {"425",{ "x1", "y2", "x3", "x4", "x5", "x6", "+", "+", "+", "+" }}, {"426",{ "x1", "y2", "x3", "x4", "x5", "x6", "x7", "y8", "+", "+" }}, {"427",{ "x1", "y2", "x3", "x4", "x5", "x6", "+", "+", "+", "x10"}}, {"428",{ NULL, "x2", "y3", NULL, NULL, NULL, "+", "+", NULL, NULL }}, {"429",{ NULL, NULL, "y3", NULL, "x5", NULL, NULL, "+", NULL, "+" }}, {"TP20", { "x1",NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, {"OUTPUT", { "x1",NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, {"OUTPUT_OC",{ "x1",NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, {"OUTPUT_OE",{ "x1","x2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, {"INPUT", { "y1","y2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, {"FET-N", { "1","2", "3", NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, {NULL ,{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }} }; // // Функция вывода начального сообщения о версии и программе // void ERR_ShowStart(void) { // // printf("\n\r*** Start Message should be here ***\n\r"); // ERR_Verbose("\n\rVNET32 netlist to Verilog converting processor. " "Copyright (c) Vslav, 2001-2013 v1.0a" "\n\r"); } // // Функция вывода справочного сообщения // void ERR_ShowHelp(void) { // // printf("\n\r*** Help Message should be here ***\n\r"); // printf("\n\rVNET32 netlist to Verilog preprocessor. " "Copyright (c) Vslav, 2001-2013 v1.0a" "\n\r"); printf( "\n\rUsage: vnet32 [{/|-} [...]]] " "\n\rSwitches:" "\n\r -# - verbose operations" "\n\r -p_ - select processing mode" "\n\r 0 - VP1 schematic" "\n\r 1 - VM1 main matrix" "\n\r 2 - VM1 interrupt matrix" "\n\r 3 - VM2 branch matrix" "\n\r 4 - VM2 interrupt matrix" "\n\r 5 - VM2 main matrix" "\n\r 6 - VM2 predecoder matrix" "\n\r -? - display this help message" "\n\r" "\n\r" ); } // // Функция вывода диагностических сообщений // void __cdecl ERR_Verbose(char* Format, ...) { if (CL_KeyPresent(KEY_VERB_BIT)) { va_list ArgList; va_start(ArgList, Format); vprintf(Format, ArgList); } } // // Операции могут выполняться долго, обеспечим корректный выход по Ctrl+C // BOOL WINAPI CtrlHandlerRoutine(DWORD dwCtrlType) { ERR_ShowError(ERR_FATAL"Operation is interrupted by user\n\r"); return FALSE; } void Replace_Tilda(char* text) { char* look; look = text; do { look = strchr(look, '~'); if (look == NULL) break; *look++ = 'n'; } while(TRUE); } int Comp_Find(char *text) { int n; n = ncomp; if (n) { PCMP pcmp; pcmp = cmp; do { if (strcmp(pcmp->name, text) == 0) { return pcmp - cmp; } pcmp++; } while(--n); } return -1; } int Type_Find(char* text) { PTYP ptyp; ptyp = typ; do { if (strcmp(text, ptyp->name) == 0) { return ptyp - typ; } ptyp++; } while(ptyp->name != NULL); return -1; } int Token_Recognize(char* text) { if (strcmp(text, "asciiHeader") == 0) return TOKEN_ASCHDR; if (strcmp(text, "netlist") == 0) return TOKEN_NETLIST; if (strcmp(text, "compInst") == 0) return TOKEN_COMPINST; if (strcmp(text, "compRef") == 0) return TOKEN_COMPREF; if (strcmp(text, "originalName") == 0) return TOKEN_ORGNAME; if (strcmp(text, "compValue") == 0) return TOKEN_COMPVALUE; if (strcmp(text, "patternName") == 0) return TOKEN_PRTNAME; if (strcmp(text, "net") == 0) return TOKEN_NET; if (strcmp(text, "node") == 0) return TOKEN_NODE; if (strcmp(text, "ACCEL_ASCII") == 0) return TOKEN_ACCEL; return TOKEN_UNKNOWN; } int Token_Fetch(char* text) { BOOL in, qt; char* store; do { if (pline < 0) { // // Предыдущая строка исчерпана // pline = FL_ReadLine(Input, Line); if (pline < 0) { // // Произошла ошибка (при этом сообщение уже выведено // функцией чтения строки) или банальный конец файла // return TOKEN_EOF; } nline++; dline = 0; } in = FALSE; qt = FALSE; store = text; while(dline <= pline) { char c; c = Line[dline]; dline++; if (in) { // // Находимся в обработке токена // if (c == ')') { dline--; *store++ = 0; return Token_Recognize(text); } if (c == 0) { // // Конец строки // pline = -1; *store++ = 0; return Token_Recognize(text); } if ((c == 9) || (c == 32)) { // // Конец токена // *store++ = 0; return Token_Recognize(text); } *store++ = c; if ((store - text) >= TOKEN_MAX) { ERR_ShowError(ERR_FATAL"Line %d contains too long token\n\r", nline); return TOKEN_EOF; } continue; } if (qt) { // // Находимся в обработке кавычек // if (c == 0) { // // Конец строки, кавычки незавершены // pline = -1; ERR_ShowError(ERR_FATAL"Line %d contains not paired quotes\n\r", nline); return TOKEN_EOF; } if (c == '"') { // // Завершение кавычек // *store++ = 0; return TOKEN_QUOTE; } *store++ =c; continue; } if (c == 0) { break; } if ((c == 9) || (c == 32)) { continue; } if (c == '"') { qt = TRUE; continue; } if (c == '(') { *store++ = 0; return TOKEN_OPEN; } if (c == ')') { *store++ = 0; return TOKEN_CLOSE; } *store++ = c; in = TRUE; } pline = -1; } while(TRUE); } // // Загрузка нетлиста из файла // int LoadNetlist(void) { int token, prev; int nskip, ignor; int i; char state; token = TOKEN_EOF; state = STATE_IDLE; ignor = 0; nline = 0; ncomp = 0; nnode = 0; nnet = 0; nskip = 0; pline = -1; for(;;) { prev = token; token = Token_Fetch(Token); if (token == TOKEN_EOF) { // // Произошла ошибка (при этом сообщение уже выведено // функцией чтения строки) или банальный конец файла // if (nskip != 0) { ERR_ShowError(ERR_FATAL"Unexpected end of file (not closed skip)\n\r"); return -1; } break; } // // Игнорируем все токены в режиме пропуска // if (nskip) { if (token == TOKEN_CLOSE) { nskip--; continue; } if (token == TOKEN_OPEN) { nskip++; continue; } continue; } if (token == TOKEN_UNKNOWN) { ERR_ShowError(ERR_FATAL"Line %d contains unrecognized token \"%s\"\n\r", nline, Token); return -1; } if (ignor) { ignor--; continue; } if (token == TOKEN_ASCHDR) { nskip = 1; continue; } if (token == TOKEN_ACCEL) { ignor = 1; continue; } if (token == TOKEN_OPEN) { continue; } // // printf("\r\n%d: %d, %d, %d, %s", nline, token, prev, state, Token); // switch(state) { case STATE_IDLE: { if (token == TOKEN_NETLIST) { if (prev == TOKEN_OPEN) { state = STATE_NETLIST; ignor = 1; continue; } } ERR_ShowError(ERR_FATAL"Syntax error [%d] in line %d\n\r", __LINE__, nline); return -1; } case STATE_NETLIST: { if (token == TOKEN_CLOSE) { state = STATE_IDLE; break; } if (prev == TOKEN_OPEN) { if (token == TOKEN_COMPINST) { state = STATE_COMP; continue; } if (token == TOKEN_NET) { state = STATE_NET; continue; } } ERR_ShowError(ERR_FATAL"Syntax error [%d] in line %d\n\r", __LINE__, nline); return -1; } case STATE_COMP: { if (prev == TOKEN_COMPINST) { if (token != TOKEN_QUOTE) { ERR_ShowError(ERR_FATAL"Syntax error [%d] in line %d\n\r", __LINE__, nline); return -1; } if (ncomp >= CMP_MAX) { ERR_ShowError(ERR_FATAL"Too many components in the netlist\n\r"); return -1; } if (strlen(Token) >= CMP_NAME_MAX) { ERR_ShowError(ERR_FATAL"Too long component name \"%s\" in line %d\n\r", Token, nline); return -1; } // // Добавление нового компонента // strcpy(cmp[ncomp].name, Token); cmp[ncomp].type = -1; for(i=0; i= CMP_NAME_MAX) { ERR_ShowError(ERR_FATAL"Too long component value \"%s\" in line %d\n\r", Token, nline); return -1; } Replace_Tilda(Token); strcpy(cmp[ncomp-1].value, Token); } nskip = 1; break; } ERR_ShowError(ERR_FATAL"Syntax error [%d] in line %d\n\r", __LINE__, nline); return -1; } case STATE_NET: { if (prev == TOKEN_NET) { if (token != TOKEN_QUOTE) { ERR_ShowError(ERR_FATAL"Syntax error [%d] in line %d\n\r", __LINE__, nline); return -1; } // // Cоздание новой цепи // if (nnet >= NET_MAX) { ERR_ShowError(ERR_FATAL"Too many nets in the netlist\n\r"); return -1; } if (strlen(Token) >= NET_NAME_MAX) { ERR_ShowError(ERR_FATAL"Too long net name \"%s\" in line %d\n\r", Token, nline); return -1; } Replace_Tilda(Token); strcpy(net[nnet].name, Token); nnet++; ERR_Verbose("\r\nAdding network: %s", Token); continue; } if (token == TOKEN_CLOSE) { state = STATE_NETLIST; break; } if (prev == TOKEN_OPEN) { switch(token) { case TOKEN_NODE: { break; } default: { ERR_ShowError(ERR_FATAL"Syntax error [%d] in line %d\n\r", __LINE__, nline); return -1; } } continue; } if (token == TOKEN_QUOTE) { if (prev == TOKEN_NODE) { nodecomp = Comp_Find(Token); if (nodecomp < 0) { ERR_ShowError(ERR_FATAL"Component \"%s\" not found in line %d\n\r", Token, nline); return -1; } state = STATE_NODE; continue; } nskip = 1; continue; } ERR_ShowError(ERR_FATAL"Syntax error [%d] in line %d\n\r", __LINE__, nline); return -1; } case STATE_NODE: { if (prev == TOKEN_QUOTE) { int pin; pin = atoi(Token); if ((pin == 0) || (pin > PIN_MAX)) { ERR_ShowError(ERR_FATAL"Invalid pin number \"%s\" in line %d\n\r", Token, nline); return -1; } pin--; if (cmp[nodecomp].pin[pin] >= 0) { ERR_ShowError(ERR_FATAL"Pin %d is already connected in line %d\n\r", pin+1, nline); return -1; } if (typ[cmp[nodecomp].type].pin[pin] == NULL) { ERR_ShowError(ERR_FATAL"Attempt to connect to unavailable pin %d in line %d\n\r", pin+1, nline); return -1; } if (*(typ[cmp[nodecomp].type].pin[pin]) != '+') { cmp[nodecomp].pin[pin] = nnet - 1; ERR_Verbose("\r\nAdding node: %s->%s[%d]", net[nnet-1].name, cmp[nodecomp].name, pin+1); } state = STATE_NET; nskip = 1; continue; } ERR_ShowError(ERR_FATAL"Syntax error [%d] in line %d\n\r", __LINE__, nline); return -1; } default: { ERR_ShowError(ERR_DEBUG"Invalid state %d\n\r", state); return -1; } } if (token == TOKEN_CLOSE) continue; } return 0; } // // Собственно функция обработки // Переводит весь список цепей в Verilog // void Execute0(void) { int token, i; // // Загружаем список цепей // if (LoadNetlist() < 0) { return; } // // Записываем собранную базу цепей в формате Verilog // if (nnet != 0) { PNET pnet; int n; pnet = net; n = nnet; do { if ( (pnet->name[0] != 'N') || (pnet->name[1] != 'E') || (pnet->name[2] != 'T')) { wsprintf(Line, "wire %s;", pnet->name); token = FL_WriteLine(Output, Line); if (token < 0) { // // Произошла ошибка записи в выходной файл // break; } } pnet++; } while(--n); pnet = net; n = nnet; do { if ( (pnet->name[0] == 'N') && (pnet->name[1] == 'E') && (pnet->name[2] == 'T')) { wsprintf(Line, "wire %s;", pnet->name); token = FL_WriteLine(Output, Line); if (token < 0) { // // Произошла ошибка записи в выходной файл // break; } } pnet++; } while(--n); } if (ncomp != 0) { PCMP pcmp; int n; pcmp = cmp; n = ncomp; do { PTYP ptyp; BOOL f; int l; ptyp = typ + pcmp->type; l = 0; l = wsprintf(Line, "t%s cell_%s(", ptyp->name, pcmp->name); f = TRUE; for(i=0; ipin[i] >= 0) { if (f) { l += wsprintf(Line + l, ".%s(%s)", ptyp->pin[i], net[pcmp->pin[i]].name); f = FALSE; } else { l += wsprintf(Line + l, ", .%s(%s)", ptyp->pin[i], net[pcmp->pin[i]].name); } } } if ( (pcmp->name[0] == 'P') && (pcmp->name[1] == 'I') && (pcmp->name[2] == 'N')) { l += wsprintf(Line + l, ", PIN_%s", pcmp->value); } l += wsprintf(Line + l, ");"); token = FL_WriteLine(Output, Line); if (token < 0) { // // Произошла ошибка записи в выходной файл // break; } pcmp++; } while(--n); } } // // Возвращает TRUE если цепь имеет имя P{число} // BOOL IsNetP(PNET pnet) { char *p; if (pnet->name[0] != 'P') { return FALSE; } p = &pnet->name[1]; do { if (!isdigit(*p)) { return FALSE; } p++; } while(*p); return TRUE; } BOOL IsNetPL(PNET pnet) { char *p; if (pnet->name[0] != 'P') { return FALSE; } if (pnet->name[1] != 'L') { return FALSE; } p = &pnet->name[2]; do { if (!isdigit(*p)) { return FALSE; } p++; } while(*p); return TRUE; } int FindNetPL(int i) { PNET pnet; int n; n = 0; do { pnet = &net[n]; if (IsNetPL(pnet)) { int pn; // // Обнаружена цепь Sum-of-Product (вида PL{число}) // Pаспознаем номер цепи PL // pn = atoi(&pnet->name[2]); if ((pn < 0) || (pn >= SOP_MAX)) { ERR_ShowError(ERR_FATAL"Invalid sum-of-product number(%d)", pn); return -1; } if (pn == i) { return n; } } n++; } while(n < nnet); return -1; } // // Собственно функция обработки // Переводит список цепей из PLM (имя формата P{число}) в verilog // void Execute1(void) { PNET pnet; int n, i, c, pn, l; // // Загружаем список цепей // if ((LoadNetlist() < 0) || (nnet == 0)) { return; } memset(ir_prod_l, 0, sizeof(ir_prod_l)); memset(ir_prod_h, 0, sizeof(ir_prod_h)); memset(mr_prod_l, 0, sizeof(mr_prod_l)); memset(mr_prod_h, 0, sizeof(mr_prod_h)); // // Сканируем все цепи P{число} // n = 0; do { pnet = &net[n]; if (IsNetP(pnet)) { // // Обнаружена цепь Product (вида P{число}) // Pаспознаем номер цепи P // pn = atoi(&pnet->name[1]); if ((pn < 0) || (pn >= PRO_MAX)) { ERR_ShowError(ERR_FATAL"Invalid product number(%d)", pn); return; } // // Теперь ищем транзистор-переходник // for(c=0; c%s->%s", pn, pnet->name, cmp[c].name, pnew->name); // // Перебираем все транзисторы, подключенные к данной цепи // for(c=0; c= 0) { t = cmp[c].pin[1]; } ERR_Verbose(" %s", net[t].name); // // Распознаем инверсию цепи // if (net[t].name[0] == 'n') { xn = atoi(&net[t].name[2]); if (net[t].name[1] == 'I') { ir_prod_h[pn] |= (1<name); if (i < 10) { l = wsprintf(Line, "assign pl[%d] = ", i); } else { if (i < 100) { l = wsprintf(Line, "assign pl[%d] = ", i); } else { l = wsprintf(Line, "assign pl[%d] = ", i); } } first = TRUE; for(pn = PRO_MAX-1; pn >=0 ; pn--) { // // Теперь ищем транзисторы матрицы // for(c=0; c= FL_LINSIZE) { ERR_ShowError(ERR_FATAL"Line too long"); return; } } } } } } wsprintf(Line + l, ";"); n = FL_WriteLine(Output, Line); if (n < 0) { // // Произошла ошибка записи в выходной файл // break; } } } // // Возвращает TRUE если цепь имеет имя G{число} // BOOL IsNetG(PNET pnet) { char *p; if (pnet->name[0] != 'G') { return FALSE; } p = &pnet->name[1]; do { if (!isdigit(*p)) { return FALSE; } p++; } while(*p); return TRUE; } BOOL IsNetPLI(PNET pnet) { char *p; if (pnet->name[0] != 'P') { return FALSE; } if (pnet->name[1] != 'L') { return FALSE; } if (pnet->name[2] != 'I') { return FALSE; } p = &pnet->name[3]; do { if (!isdigit(*p)) { return FALSE; } p++; } while(*p); return TRUE; } BOOL IsNetPLB(PNET pnet) { char *p; if (pnet->name[0] != 'P') { return FALSE; } if (pnet->name[1] != 'L') { return FALSE; } if (pnet->name[2] != 'B') { return FALSE; } p = &pnet->name[3]; do { if (!isdigit(*p)) { return FALSE; } p++; } while(*p); return TRUE; } int FindNetPLI(int i) { PNET pnet; int n; n = 0; do { pnet = &net[n]; if (IsNetPLI(pnet)) { int pn; // // Обнаружена цепь Sum-of-Product (вида PL{число}) // Pаспознаем номер цепи PL // pn = atoi(&pnet->name[3]); if ((pn < 0) || (pn >= SOP_MAX)) { ERR_ShowError(ERR_FATAL"Invalid sum-of-product number(%d)", pn); return -1; } if (pn == i) { return n; } } n++; } while(n < nnet); return -1; } int FindNetPLB(int i) { PNET pnet; int n; n = 0; do { pnet = &net[n]; if (IsNetPLB(pnet)) { int pn; // // Обнаружена цепь Sum-of-Product (вида PLB{число}) // Pаспознаем номер цепи PLB // pn = atoi(&pnet->name[3]); if ((pn < 0) || (pn >= SOP_MAX)) { ERR_ShowError(ERR_FATAL"Invalid sum-of-product number(%d)", pn); return -1; } if (pn == i) { return n; } } n++; } while(n < nnet); return -1; } // // Собственно функция обработки // Переводит список цепей из PLI (имя формата G{число}) в verilog // Для 1801ВМ1 // void Execute2(void) { PNET pnet; int n, i, c, pn, l; // // Загружаем список цепей // if ((LoadNetlist() < 0) || (nnet == 0)) { return; } memset(ir_prod_l, 0, sizeof(ir_prod_l)); memset(ir_prod_h, 0, sizeof(ir_prod_h)); memset(mr_prod_l, 0, sizeof(mr_prod_l)); memset(mr_prod_h, 0, sizeof(mr_prod_h)); // // Сканируем все цепи G{число} // n = 0; do { pnet = &net[n]; if (IsNetG(pnet)) { // // Обнаружена цепь Product (вида G{число}) // Pаспознаем номер цепи P // pn = atoi(&pnet->name[1]); if ((pn < 0) || (pn >= PRO_MAX)) { ERR_ShowError(ERR_FATAL"Invalid product number(%d)", pn); return; } // // Теперь ищем транзистор-переходник // for(c=0; c%s->%s", pn, pnet->name, cmp[c].name, pnew->name); // // Перебираем все транзисторы, подключенные к данной цепи // for(c=0; c= 0) { t = cmp[c].pin[1]; } ERR_Verbose(" %s", net[t].name); // // Распознаем инверсию цепи // if (net[t].name[0] == 'n') { xn = atoi(&net[t].name[3]); ir_prod_h[pn] |= (1<name); if (i < 10) { l = wsprintf(Line, "assign sp[%d] = ", i); } else { if (i < 100) { l = wsprintf(Line, "assign sp[%d] = ", i); } else { l = wsprintf(Line, "assign sp[%d] = ", i); } } first = TRUE; for(pn = PRO_MAX-1; pn >=0 ; pn--) { // // Теперь ищем транзисторы матрицы // for(c=0; c= FL_LINSIZE) { ERR_ShowError(ERR_FATAL"Line too long"); return; } } } } } } wsprintf(Line + l, ";"); n = FL_WriteLine(Output, Line); if (n < 0) { // // Произошла ошибка записи в выходной файл // break; } } } // // Матрица ветвления 1801ВМ2 // void Execute3(void) { PNET pnet; int n, i, c, pn; // // Загружаем список цепей // if ((LoadNetlist() < 0) || (nnet == 0)) { return; } memset(ir_prod_l, 0, sizeof(ir_prod_l)); memset(ir_prod_h, 0, sizeof(ir_prod_h)); memset(mr_prod_l, 0, sizeof(mr_prod_l)); memset(mr_prod_h, 0, sizeof(mr_prod_h)); // // Сканируем все цепи G{число} // n = 0; do { pnet = &net[n]; if (IsNetG(pnet)) { // // Обнаружена цепь Product (вида G{число}) // Pаспознаем номер цепи P // pn = atoi(&pnet->name[1]); if ((pn < 0) || (pn >= PRO_MAX)) { ERR_ShowError(ERR_FATAL"Invalid product number(%d)", pn); return; } // // Перебираем все транзисторы: // - подключенные стоком к данной цепи и истоком к GND-B // for(c=0; cname, "GND-B") != 0) { continue; } // // Смотрим что на затворе // p = cmp[c].pin[1]; pnew = &net[p]; ERR_Verbose("\r\nProduct(%d): %s->%s->%s", pn, pnet->name, cmp[c].name, pnew->name); // // Распознаем инверсию цепи // if (pnew->name[0] == 'n') { if (pnew->name[1] != 'B') { ERR_ShowError(ERR_FATAL"Invalid attached nPI-net(%d, %s)", pn, pnew->name); return; } xn = atoi(&pnew->name[2]); ir_prod_h[pn] |= (1<name[0] != 'B') { ERR_ShowError(ERR_FATAL"Invalid attached PI-net(%d, %s)", pn, pnew->name); return; } xn = atoi(&pnew->name[1]); ir_prod_l[pn] |= (1<name[1]); if ((pn < 0) || (pn >= PRO_MAX)) { ERR_ShowError(ERR_FATAL"Invalid product number(%d)", pn); return; } // // Перебираем все транзисторы: // - подключенные стоком к данной цепи и истоком к GND-A // - подключенные затвором к данной цепи и истоком к GND-I // for(c=0; cname, "GND-A") != 0) { continue; } // // Смотрим что на затворе // p = cmp[c].pin[1]; pnew = &net[p]; ERR_Verbose("\r\nProduct(%d): %s->%s->%s", pn, pnet->name, cmp[c].name, pnew->name); // // Распознаем инверсию цепи // if (pnew->name[0] == 'n') { if ((pnew->name[1] != 'P') || (pnew->name[2] != 'I')) { ERR_ShowError(ERR_FATAL"Invalid attached nPI-net(%d, %s)", pn, pnew->name); return; } xn = atoi(&pnew->name[3]); ir_prod_h[pn] |= (1<name[0] != 'P') || (pnew->name[1] != 'I')) { ERR_ShowError(ERR_FATAL"Invalid attached PI-net(%d, %s)", pn, pnew->name); return; } xn = atoi(&pnew->name[2]); ir_prod_l[pn] |= (1<name, "GND-I") != 0) { continue; } // // Смотрим что на стоке, должно быть PLIxx // p = cmp[c].pin[2]; pnew = &net[p]; if (IsNetPLI(pnew)) { xn = atoi(&pnew->name[3]); if ((xn < 0) || (xn >= SOP_MAX)) { ERR_ShowError(ERR_FATAL"Invalid sum-of-product number(%d)", pn); return; } mr_prod_l[xn] |= (1<name); if (i < 10) { l = wsprintf(Line, "assign sp[%d] = ", i); } else { if (i < 100) { l = wsprintf(Line, "assign sp[%d] = ", i); } else { l = wsprintf(Line, "assign sp[%d] = ", i); } } first = TRUE; for(pn = 31; pn >=0 ; pn--) { if (mr_prod_l[i] & (1<= FL_LINSIZE) { ERR_ShowError(ERR_FATAL"Line too long"); return; } } } wsprintf(Line + l, ";"); n = FL_WriteLine(Output, Line); if (n < 0) { // // Произошла ошибка записи в выходной файл // break; } } } // // Основная матрица микрокода 1801ВМ2 // void Execute5(void) { PNET pnet; int n, i, c, pn, l; // // Загружаем список цепей // if ((LoadNetlist() < 0) || (nnet == 0)) { return; } memset(ir_prod_l, 0, sizeof(ir_prod_l)); memset(ir_prod_h, 0, sizeof(ir_prod_h)); memset(mr_prod_l, 0, sizeof(mr_prod_l)); memset(mr_prod_h, 0, sizeof(mr_prod_h)); // // Сканируем все цепи P{число} // n = 0; do { pnet = &net[n]; if (IsNetP(pnet)) { // // Обнаружена цепь Product (вида P{число}) // Pаспознаем номер цепи P // pn = atoi(&pnet->name[1]); if ((pn < 0) || (pn >= PRO_MAX)) { ERR_ShowError(ERR_FATAL"Invalid product number(%d)", pn); return; } // // Перебираем все транзисторы: // - подключенные стоком к данной цепи и истоком к GND-P // - подключенные затвором к данной цепи и истоком к GND-S // for(c=0; cname, "GND-P") != 0) { continue; } // // Смотрим что на затворе // p = cmp[c].pin[1]; pnew = &net[p]; ERR_Verbose("\r\nProduct(%d): %s->%s->%s", pn, pnet->name, cmp[c].name, pnew->name); // // Распознаем инверсию цепи // b = (pnew->name[0] == 'n') ? 1 : 0; if ((pnew->name[b+0] == 'I') && (pnew->name[b+1] == 'A')) { xn = atoi(&pnew->name[b+2]) + 16; } else { if ((pnew->name[b+0] == 'I') && (pnew->name[b+1] == 'X')) { xn = atoi(&pnew->name[b+2]) + 22; } else { if ((pnew->name[b+0] == 'R') && (pnew->name[b+1] == 'I')) { xn = atoi(&pnew->name[b+2]) + 25; } else { if (pnew->name[b+0] == 'I') { xn = atoi(&pnew->name[b+1]); } else { ERR_ShowError(ERR_FATAL"Invalid attached nPI-net(%d, %s)", pn, pnew->name); return; } } } } if (b) { ir_prod_h[pn] |= (1<name, "GND-S") != 0) { continue; } // // Смотрим что на стоке, должно быть PLxx // p = cmp[c].pin[2]; pnew = &net[p]; if (IsNetPL(pnew)) { xn = atoi(&pnew->name[2]); if ((xn < 0) || (xn >= SOP_MAX)) { ERR_ShowError(ERR_FATAL"Invalid sum-of-product number(%d)", pn); return; } if (xn < 32) { mr_prod_l[pn] |= (1<name); if (i < 10) { l = wsprintf(Line, "assign pl[%d] = ", i); } else { if (i < 100) { l = wsprintf(Line, "assign pl[%d] = ", i); } else { l = wsprintf(Line, "assign pl[%d] = ", i); } } first = TRUE; for(pn = PRO_MAX-1; pn >=0 ; pn--) { // // Теперь ищем транзисторы матрицы // if (i < 32) { if ((mr_prod_l[pn] & (1<= FL_LINSIZE) { ERR_ShowError(ERR_FATAL"Line too long"); return; } } wsprintf(Line + l, ";"); n = FL_WriteLine(Output, Line); if (n < 0) { // // Произошла ошибка записи в выходной файл // break; } } } // // Матрица предекодера 1801ВМ2 // void Execute6(void) { PNET pnet; int n, i, c, pn, l; // // Загружаем список цепей // if ((LoadNetlist() < 0) || (nnet == 0)) { return; } memset(ir_prod_l, 0, sizeof(ir_prod_l)); memset(ir_prod_h, 0, sizeof(ir_prod_h)); memset(mr_prod_l, 0, sizeof(mr_prod_l)); memset(mr_prod_h, 0, sizeof(mr_prod_h)); // // Сканируем все цепи G{число} // n = 0; do { pnet = &net[n]; if (IsNetG(pnet)) { // // Обнаружена цепь Product (вида G{число}) // Pаспознаем номер цепи P // pn = atoi(&pnet->name[1]); if ((pn < 0) || (pn >= PRO_MAX)) { ERR_ShowError(ERR_FATAL"Invalid product number(%d)", pn); return; } // // Перебираем все транзисторы: // - подключенные стоком к данной цепи и истоком к GND-D // - подключенные затвором к данной цепи и истоком к GND-C // for(c=0; cname, "GND-D") != 0) { continue; } // // Смотрим что на затворе // p = cmp[c].pin[1]; pnew = &net[p]; ERR_Verbose("\r\nProduct(%d): %s->%s->%s", pn, pnet->name, cmp[c].name, pnew->name); // // Распознаем инверсию цепи // if (pnew->name[0] == 'n') { if ((pnew->name[1] != 'B') || (pnew->name[2] != 'I')) { ERR_ShowError(ERR_FATAL"Invalid attached nBI-net(%d, %s)", pn, pnew->name); return; } xn = atoi(&pnew->name[3]); ir_prod_h[pn] |= (1<name[0] != 'B') || (pnew->name[1] != 'I')) { ERR_ShowError(ERR_FATAL"Invalid attached BI-net(%d, %s)", pn, pnew->name); return; } xn = atoi(&pnew->name[2]); ir_prod_l[pn] |= (1<name, "GND-C") != 0) { continue; } // // Смотрим что на стоке, должно быть PLBxx // p = cmp[c].pin[2]; pnew = &net[p]; if (IsNetPLB(pnew)) { xn = atoi(&pnew->name[3]); if ((xn < 0) || (xn >= SOP_MAX)) { ERR_ShowError(ERR_FATAL"Invalid sum-of-product number(%d)", pn); return; } mr_prod_l[pn] |= (1<name); if (i < 10) { l = wsprintf(Line, "assign sp[%d] = ", i); } else { if (i < 100) { l = wsprintf(Line, "assign sp[%d] = ", i); } else { l = wsprintf(Line, "assign sp[%d] = ", i); } } first = TRUE; for(pn = PRO_MAX-1; pn >=0 ; pn--) { if (mr_prod_l[pn] & (1<= FL_LINSIZE) { ERR_ShowError(ERR_FATAL"Line too long"); return; } } } wsprintf(Line + l, ";"); n = FL_WriteLine(Output, Line); if (n < 0) { // // Произошла ошибка записи в выходной файл // break; } } } int __cdecl main(int argc, char* argv[]) { int ExitCode = -1; DWORD mode; // // Выводим сообщение о запуске программы // ERR_ShowStart(); __try { char* Name; SetConsoleCtrlHandler( CtrlHandlerRoutine, TRUE); // // Сначала обрабатываем конмандную строку // Если возникает ошибка, то просто выходим // if (CL_ParseCmdLine( argc, argv)) __leave; if (CL_KeyPresent(KEY_HELP_BIT)) { ERR_ShowHelp(); __leave; } // // Сначала открываем входной файл на чтение // Name = CL_GetInFile(); if(Name == NULL) { ERR_ShowError(ERR_FATAL"Input file name is not specified\n\r"); __leave; } ERR_Verbose("\r\nInput file name : %s", Name); Input = FL_Open(Name, FL_BUFSIZE); if (Input == NULL) { ERR_ShowError(ERR_FATAL"Input file open failure\n\r"); __leave; } // // Создаем пустой выходной файл и готовимся к записи // Name = CL_GetOutFile(); if(Name == NULL) { ERR_ShowError(ERR_FATAL"Output file name is not specified\n\r"); __leave; } ERR_Verbose("\r\nOutput file name: %s", Name); Output = FL_Create(Name, FL_BUFSIZE); if (Output == NULL) { ERR_ShowError(ERR_FATAL"Output file creation failure\n\r"); __leave; } mode = 0; if (CL_KeyPresent(KEY_P_BIT)) { mode = *(DWORD*)CL_GetValuePtr(KEY_P_BIT); } // // Выполняем требуемую обработку // switch(mode) { case 0: { // // Обработка цепей 1801ВП1 // Execute0(); break; } case 1: { // // Основная матрица микрокода 1801ВМ1 // Execute1(); break; } case 2: { // // Матрица прерываний 1801ВМ1 // Execute2(); break; } case 3: { // // Матрица ветвления 1801ВМ2 // Execute3(); break; } case 4: { // // Матрица прерываний 1801ВМ2 // Execute4(); break; } case 5: { // // Основная матрица микрокода 1801ВМ2 // Execute5(); break; } case 6: { // // Матрица предекодера 1801ВМ2 // Execute6(); break; } default: { ERR_ShowError(ERR_DEBUG"Unimplemented processing mode\n\r"); break; } } // // Закрываем открытые файлы // FL_Close(Input); Input = NULL; FL_Close(Output); Output = NULL; ERR_Verbose("\n"); // // Все операции успешно выполнены // ExitCode = 0; SetConsoleCtrlHandler( CtrlHandlerRoutine, FALSE); } __finally { // // Производим освобождение всех использованных ресурсов // if (Input != NULL) { FL_Close(Input); Input = NULL; } if (Output != NULL) { FL_Close(Output); Output = NULL; } } exit(ExitCode); }