PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/dgc-0.98/cube/fsmmin.c

#
C | 522 lines | 380 code | 68 blank | 74 comment | 136 complexity | 323e99f321f40b198bcbc34c2ea05717 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. fsmmin.c
  3. minimization of finite state machines
  4. Copyright (C) 2001 Oliver Kraus (olikraus@yahoo.com)
  5. This file is part of DGC.
  6. DGC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. DGC is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with DGC; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. The current algorithm could be improved very very much!!!
  18. Probably we had to solve a binate cover problem to get an exact
  19. result.
  20. */
  21. #include "b_il.h"
  22. #include "fsm.h"
  23. static int dcl_is_fbo_compatible(pinfo *pi, dclist c1, dclist c2)
  24. {
  25. dclist a, b, c;
  26. int i, cnt;
  27. if ( dclPrimes(pi, c1) == 0 )
  28. return 0;
  29. if ( dclPrimes(pi, c2) == 0 )
  30. return 0;
  31. cnt = dclCnt(c1);
  32. if ( cnt > 1 )
  33. for( i = 1; i < cnt; i++ )
  34. if ( dcIsEqualOut(pi, dclGet(c1, 0), dclGet(c1, i)) != 0 )
  35. return 0;
  36. cnt = dclCnt(c2);
  37. if ( cnt > 1 )
  38. for( i = 1; i < cnt; i++ )
  39. if ( dcIsEqualOut(pi, dclGet(c2, 0), dclGet(c2, i)) != 0 )
  40. return 0;
  41. for( i = 0; i < pi->out_cnt; i++ )
  42. if ( dcGetOut(dclGet(c1, 0), i) != dcGetOut(dclGet(c2, 0), i) )
  43. return 1;
  44. return 0;
  45. }
  46. static int dcl_is_mealy_output_compatible(pinfo *pi, dclist c1, dclist c2)
  47. {
  48. dclist a, b, c;
  49. int i, cnt;
  50. if ( dclInitVA(3, &a, &b, &c) == 0 )
  51. return 0;
  52. /* make a copy of the lists */
  53. if ( dclCopy(pi, a, c1) == 0 )
  54. return dclDestroyVA(3, a, b, c), 0;
  55. if ( dclCopy(pi, b, c2) == 0 )
  56. return dclDestroyVA(3, a, b, c), 0;
  57. /* remove the output parts (only consider inputs) */
  58. cnt = dclCnt(a);
  59. for( i = 0; i < cnt; i++ )
  60. dcSetOutTautology(pi, dclGet(a, i));
  61. cnt = dclCnt(b);
  62. for( i = 0; i < cnt; i++ )
  63. dcSetOutTautology(pi, dclGet(b, i));
  64. /* calculate the intersection: c = intersection(a,b) */
  65. if ( dclIntersectionList(pi, c, a, b) == 0 )
  66. return dclDestroyVA(3, a, b, c), 0;
  67. /* output is compatible, if the intersection is empty */
  68. if ( dclCnt(c) == 0 )
  69. return dclDestroyVA(3, a, b, c), 1;
  70. /* output is compatible if a and b are equal under the same input */
  71. /* restrict c1 into a and c2 into b */
  72. if ( dclIntersectionList(pi, a, c1, c) == 0 )
  73. return dclDestroyVA(3, a, b, c), 0;
  74. if ( dclIntersectionList(pi, b, c2, c) == 0 )
  75. return dclDestroyVA(3, a, b, c), 0;
  76. /* now check if a and b are equal */
  77. if ( dclIsEquivalent(pi, a, b) != 0 )
  78. return dclDestroyVA(3, a, b, c), 1;
  79. return dclDestroyVA(3, a, b, c), 0;
  80. }
  81. int dcl_is_output_compatible(pinfo *pi, dclist c1, dclist c2)
  82. {
  83. dcube *r1 = &(pi->tmp[13]);
  84. dcube *r2 = &(pi->tmp[14]);
  85. dclOrElements(pi, r1, c1);
  86. dclOrElements(pi, r2, c2);
  87. return dcIsEqualOut(pi, r1, r2);
  88. }
  89. static int hm_xy_to_pos(int x, int y)
  90. {
  91. if ( x == y )
  92. return -1;
  93. if ( x > y )
  94. return (x-1)*x/2 + y;
  95. return (y-1)*y/2 + x;
  96. }
  97. /*---------------------------------------------------------------------------*/
  98. struct _hm_struct
  99. {
  100. fsm_type fsm;
  101. int n;
  102. int *m;
  103. int m_size;
  104. int *flag_list;
  105. b_pl_type pl; /* list of compatible sets */
  106. };
  107. typedef struct _hm_struct *hm_type;
  108. #include <assert.h>
  109. #include <stdlib.h>
  110. #include <string.h>
  111. hm_type hm_Open(fsm_type fsm, int n)
  112. {
  113. hm_type hm;
  114. hm = (hm_type)malloc(sizeof(struct _hm_struct));
  115. if ( hm != NULL )
  116. {
  117. hm->fsm = fsm;
  118. hm->n = n;
  119. hm->m_size = (n-1)*n/2;
  120. hm->m = (int *)malloc(sizeof(int)*hm->m_size);
  121. if ( hm->m != NULL )
  122. {
  123. memset(hm->m, 0, sizeof(int)*hm->m_size);
  124. assert(hm_xy_to_pos(0, 0) == -1 );
  125. assert(hm_xy_to_pos(0, 1) == 0 );
  126. assert(hm_xy_to_pos(1, 0) == 0 );
  127. assert(hm_xy_to_pos(0, 2) == 1 );
  128. assert(hm_xy_to_pos(1, 2) == 2 );
  129. assert(hm_xy_to_pos(2, 0) == 1 );
  130. assert(hm_xy_to_pos(2, 1) == 2 );
  131. assert(hm_xy_to_pos(0, 3) == 3 );
  132. assert(hm_xy_to_pos(1, 3) == 4 );
  133. assert(hm_xy_to_pos(2, 3) == 5 );
  134. assert(hm_xy_to_pos(3, 0) == 3 );
  135. assert(hm_xy_to_pos(3, 1) == 4 );
  136. assert(hm_xy_to_pos(3, 2) == 5 );
  137. hm->pl = b_pl_Open();
  138. if ( hm->pl != NULL )
  139. {
  140. hm->flag_list = (int *)malloc(sizeof(int)*hm->n);
  141. if ( hm->flag_list != NULL )
  142. {
  143. memset(hm->flag_list, 0, sizeof(int)*hm->n);
  144. return hm;
  145. /*
  146. hm->pi_imply = pinfoOpenInOut(b_set_Cnt(fsm->nodes), b_set_Cnt(fsm->nodes))
  147. if ( hm->pi_imply != NULL )
  148. {
  149. if ( dclInit(&(hm->cl_imply)) != 0 )
  150. {
  151. }
  152. }
  153. pinfoClose(hm->pi_imply);
  154. */
  155. }
  156. b_pl_Close(hm->pl);
  157. }
  158. free(hm->m);
  159. }
  160. free(hm);
  161. }
  162. return NULL;
  163. }
  164. b_il_type hm_GetSet(hm_type hm, int pos)
  165. {
  166. return (b_il_type)b_pl_GetVal(hm->pl, pos);
  167. }
  168. void hm_Close(hm_type hm)
  169. {
  170. int i;
  171. free(hm->flag_list);
  172. for( i = 0; i < b_pl_GetCnt(hm->pl); i++ )
  173. b_il_Close(hm_GetSet(hm, i));
  174. b_pl_Close(hm->pl);
  175. free(hm->m);
  176. free(hm);
  177. }
  178. void hm_Set(hm_type hm, int x, int y, int v)
  179. {
  180. int pos = hm_xy_to_pos(x, y);
  181. assert(pos >= 0 && pos < hm->m_size);
  182. hm->m[pos] = v;
  183. }
  184. int hm_Get(hm_type hm, int x, int y)
  185. {
  186. int pos = hm_xy_to_pos(x, y);
  187. assert(pos >= 0 && pos < hm->m_size);
  188. return hm->m[pos];
  189. }
  190. int hm_IsSetCompatible(hm_type hm, b_il_type il, int s)
  191. {
  192. int i;
  193. for( i = 0; i < b_il_GetCnt(il); i++ )
  194. if ( hm_Get(hm, b_il_GetVal(il, i), s) == 0 )
  195. return 0;
  196. return 1;
  197. }
  198. /* returns position */
  199. int hm_AddEmptySet(hm_type hm)
  200. {
  201. int pos;
  202. b_il_type il;
  203. il = b_il_Open();
  204. if ( il != NULL )
  205. {
  206. pos = b_pl_Add(hm->pl, il);
  207. if ( pos >= 0 )
  208. return pos;
  209. b_il_Close(il);
  210. }
  211. return -1;
  212. }
  213. int hm_BuildCompatibleSets(hm_type hm)
  214. {
  215. int n1, n2;
  216. int pos;
  217. memset(hm->flag_list, 0, sizeof(int)*hm->n);
  218. n1 = -1;
  219. while( fsm_LoopNodes(hm->fsm, &n1) != 0 )
  220. {
  221. if ( hm->flag_list[n1] == 0 )
  222. {
  223. pos = hm_AddEmptySet(hm);
  224. if ( pos < 0 )
  225. return 0;
  226. if ( b_il_Add(hm_GetSet(hm, pos), n1) < 0 )
  227. return 0;
  228. hm->flag_list[n1] = 1;
  229. if ( fsm_SetNodeGroup(hm->fsm, n1, pos) == 0 )
  230. return 0;
  231. n2 = -1;
  232. while( fsm_LoopNodes(hm->fsm, &n2) != 0 )
  233. {
  234. if ( hm->flag_list[n2] == 0 )
  235. {
  236. if ( hm_IsSetCompatible(hm, hm_GetSet(hm, pos), n2) != 0 )
  237. {
  238. hm->flag_list[n2] = 1;
  239. if ( fsm_SetNodeGroup(hm->fsm, n2, pos) == 0 )
  240. return 0;
  241. if ( b_il_Add(hm_GetSet(hm, pos), n2) < 0 )
  242. return 0;
  243. }
  244. }
  245. }
  246. }
  247. }
  248. return 1;
  249. }
  250. #define BLEN 100
  251. void hm_ShowCompatibleSets(hm_type hm)
  252. {
  253. int i, j;
  254. b_il_type il;
  255. char s[BLEN];
  256. for( i = 0; i < b_pl_GetCnt(hm->pl); i++ )
  257. {
  258. sprintf(s, "FSM: Compatible group %d { ", i);
  259. il = hm_GetSet(hm, i);
  260. for( j = 0; j < b_il_GetCnt(il); j++ )
  261. {
  262. if( strlen(s) < BLEN-10-26-10 )
  263. {
  264. sprintf(s+strlen(s),"%s ", fsm_GetNodeNameStr(hm->fsm, b_il_GetVal(il, j)));
  265. }
  266. else
  267. {
  268. sprintf(s+strlen(s),"...");
  269. break;
  270. }
  271. }
  272. sprintf(s+strlen(s),"}");
  273. fsm_Log(hm->fsm, s);
  274. }
  275. }
  276. static int fsm_GetAllInEdgeOutput(fsm_type fsm, int n, dclist cl)
  277. {
  278. int loop, in_n;
  279. dclist cl_tmp;
  280. pinfo *pi = fsm_GetOutputPINFO(fsm);
  281. cl_tmp = fsm_GetNodeSelfOutput(fsm, n);
  282. if ( dclPrimes(pi, cl_tmp) == 0 )
  283. return 0;
  284. if ( dclCopy(pi, cl, fsm_GetNodeSelfOutput(fsm, n) ) == 0 )
  285. return 0;
  286. loop = -1;
  287. while( fsm_LoopNodeInNodes(fsm, n, &loop, &in_n) != 0 )
  288. {
  289. cl_tmp = fsm_GetNodeSelfOutput(fsm, in_n);
  290. if ( dclPrimes(pi, cl_tmp) == 0 )
  291. return 0;
  292. if ( dclSCCUnion( pi, cl, cl_tmp ) == 0 )
  293. return 0;
  294. }
  295. return 1;
  296. }
  297. static int fsm_IsFBOCompatible(fsm_type fsm, int n1, int n2)
  298. {
  299. dclist c1, c2;
  300. pinfo *pi = fsm_GetOutputPINFO(fsm);
  301. dcube *or = &(pi->tmp[13]);
  302. dcube *and = &(pi->tmp[14]);
  303. int i;
  304. if ( dclInitVA(2, &c1, &c2) == 0 )
  305. return 0;
  306. if ( fsm_GetAllInEdgeOutput(fsm, n1, c1) == 0 )
  307. return dclDestroyVA(2, c1, c2), 0;
  308. if ( fsm_GetAllInEdgeOutput(fsm, n2, c2) == 0 )
  309. return dclDestroyVA(2, c1, c2), 0;
  310. fsm_LogDCL(fsm, "FSM: ", 2, "c1", pi, c1, "c2", pi, c2);
  311. dclAndElements(pi, and, c1);
  312. dclOrElements(pi, or, c2);
  313. for( i = 0; i < pi->out_cnt; i++ )
  314. if ( dcGetOut(and, i) != 0 && dcGetOut(or, i) == 0 )
  315. return dclDestroyVA(2, c1, c2), 1;
  316. dclAndElements(pi, and, c2);
  317. dclOrElements(pi, or, c1);
  318. for( i = 0; i < pi->out_cnt; i++ )
  319. if ( dcGetOut(and, i) != 0 && dcGetOut(or, i) == 0 )
  320. return dclDestroyVA(2, c1, c2), 1;
  321. return dclDestroyVA(2, c1, c2), 0;
  322. }
  323. static int fsm_IsCompatible(fsm_type fsm, int n1, int n2, int is_fbo)
  324. {
  325. dclist c1, c2;
  326. pinfo *pi;
  327. int l1, l2;
  328. int e1, e2;
  329. int dn1, dn2;
  330. int g1, g2;
  331. if ( n1 == n2 )
  332. return 0;
  333. pi = fsm_GetOutputPINFO(fsm);
  334. /*
  335. if ( is_fbo != 0 )
  336. {
  337. if ( fsm_IsFBOCompatible(fsm, n1, n2) != 0 )
  338. {
  339. fsm_Log(fsm, "FSM: States '%s' and '%s' are fbo compatible.",
  340. fsm_GetNodeNameStr(fsm, n1), fsm_GetNodeNameStr(fsm, n2));
  341. return 1;
  342. }
  343. }
  344. */
  345. if ( dclInitVA(2, &c1, &c2) == 0 )
  346. return 0;
  347. /*
  348. fsm_GetNodePreOCover(fsm, n1, c1);
  349. fsm_GetNodePreOCover(fsm, n2, c2);
  350. */
  351. if ( fsm_GetNodeInOCover(fsm, n1, c1) == 0 )
  352. return dclDestroyVA(2, c1, c2), 0;
  353. if ( fsm_GetNodeInOCover(fsm, n2, c2) == 0 )
  354. return dclDestroyVA(2, c1, c2), 0;
  355. /* two states are not compatible, if the output is not compatible */
  356. if ( dcl_is_mealy_output_compatible(pi, c1, c2) == 0 )
  357. {
  358. fsm_Log(fsm, "FSM: States '%s' and '%s' have different outputs (not compatible).",
  359. fsm_GetNodeNameStr(fsm, n1), fsm_GetNodeNameStr(fsm, n2));
  360. /*
  361. fsm_LogDCL(fsm, "FSM: ", 2, fsm_GetNodeNameStr(fsm, n1), pi, c1,
  362. fsm_GetNodeNameStr(fsm, n2), pi, c2);
  363. */
  364. return dclDestroyVA(2, c1, c2), 0;
  365. }
  366. dclDestroyVA(2, c1, c2);
  367. /* two states are not compatible, if there exists one condition for two */
  368. /* different transitions */
  369. pi = fsm_GetConditionPINFO(fsm);
  370. l1 = -1;
  371. e1 = -1;
  372. while ( fsm_LoopNodeOutEdges(fsm, n1, &l1, &e1) != 0 )
  373. {
  374. l2 = -1;
  375. e2 = -1;
  376. while ( fsm_LoopNodeOutEdges(fsm, n2, &l2, &e2) != 0 )
  377. {
  378. c1 = fsm_GetEdgeCondition(fsm,e1);
  379. c2 = fsm_GetEdgeCondition(fsm,e2);
  380. if ( dclIsIntersection(pi, c1, c2) != 0 )
  381. {
  382. dn1 = fsm_GetEdgeDestNode(fsm, e1);
  383. dn2 = fsm_GetEdgeDestNode(fsm, e2);
  384. g1 = fsm_GetNodeGroupIndex(fsm, dn1);
  385. g2 = fsm_GetNodeGroupIndex(fsm, dn2);
  386. /* if ( g1 < 0 || g2 < 0 || g1 != g2 ) */
  387. if ( dn1 != dn2 )
  388. {
  389. fsm_Log(fsm, "FSM: States '%s' and '%s' have identical conditions for different target states.",
  390. fsm_GetNodeNameStr(fsm, n1), fsm_GetNodeNameStr(fsm, n2));
  391. return 0;
  392. }
  393. }
  394. }
  395. }
  396. fsm_Log(fsm, "FSM: States '%s' and '%s' are compatible.",
  397. fsm_GetNodeNameStr(fsm, n1), fsm_GetNodeNameStr(fsm, n2));
  398. return 1;
  399. }
  400. void hm_BuildStateMatrix(hm_type hm, int is_fbo)
  401. {
  402. int n1, n2;
  403. n1 = -1;
  404. while( fsm_LoopNodes(hm->fsm, &n1) != 0 )
  405. {
  406. n2 = -1;
  407. while( fsm_LoopNodes(hm->fsm, &n2) != 0 )
  408. if ( n1 < n2 )
  409. hm_Set(hm, n1, n2, fsm_IsCompatible(hm->fsm, n1, n2, is_fbo));
  410. }
  411. }
  412. void hm_Show(hm_type hm)
  413. {
  414. int n1, n2;
  415. for( n1 = 0; n1 < hm->n; n1++ )
  416. {
  417. for( n2 = 0; n2 < n1; n2++ )
  418. {
  419. if ( hm_Get(hm, n1, n2) == 0 )
  420. printf(".");
  421. else
  422. printf("*");
  423. }
  424. printf("\n");
  425. }
  426. }
  427. /* well, this assigns the group-index */
  428. int fsm_minimize_states(fsm_type fsm, int is_fbo)
  429. {
  430. hm_type hm;
  431. hm = hm_Open(fsm, b_set_Max(fsm->nodes));
  432. if ( hm == NULL )
  433. return 0;
  434. hm_BuildStateMatrix(hm, is_fbo);
  435. hm_BuildCompatibleSets(hm);
  436. hm_ShowCompatibleSets(hm);
  437. hm_Close(hm);
  438. return 1;
  439. }
  440. int fsm_OldMinimizeStates(fsm_type fsm, int is_fbo)
  441. {
  442. return fsm_minimize_states(fsm, is_fbo);
  443. }