|
|
1.1 root 1: /*
2: * Cisco 7200 (Predator) simulation platform.
3: * Copyright (c) 2006 Christophe Fillot ([email protected])
4: *
5: * Instruction Lookup Tables.
6: */
7:
8: #include <stdio.h>
9: #include <stdlib.h>
10: #include <unistd.h>
11: #include <string.h>
12: #include <sys/types.h>
13: #include <sys/stat.h>
14: #include <sys/mman.h>
15: #include <assert.h>
16:
17: #include "utils.h"
18: #include "hash.h"
19: #include "insn_lookup.h"
20:
21: /* Hash function for a CBM */
22: static inline u_int cbm_hash_f(void *ccbm)
23: {
24: cbm_array_t *cbm = (cbm_array_t *)ccbm;
25: char *p,*s = (char *)(cbm->tab);
26: u_int h,g,i;
27:
28: for(h=0,i=0,p=s;i<(cbm->nr_entries*sizeof(int));p+=1,i++)
29: {
30: h = (h << 4) + *p;
31: if ((g = h & 0xf0000000)) {
32: h = h ^ (g >> 24);
33: h = h ^ g;
34: }
35: }
36:
37: return(h);
38: }
39:
40: /* Comparison function for 2 CBM */
41: static inline int cbm_cmp_f(void *b1,void *b2)
42: {
43: cbm_array_t *cbm1 = (cbm_array_t *)b1;
44: cbm_array_t *cbm2 = (cbm_array_t *)b2;
45: int i;
46:
47: for(i=0;i<cbm1->nr_entries;i++)
48: if (cbm1->tab[i] != cbm2->tab[i])
49: return(FALSE);
50:
51: return(TRUE);
52: }
53:
54: /* Set bit corresponding to a rule number in a CBM */
55: static inline void cbm_set_rule(cbm_array_t *cbm,int rule_id)
56: {
57: CBM_ARRAY(cbm,(rule_id >> CBM_SHIFT)) |= 1 << (rule_id & (CBM_SIZE-1));
58: }
59:
60: /* Clear bit corresponding to a rule number in a CBM */
61: static inline void cbm_unset_rule(cbm_array_t *cbm,int rule_id)
62: {
63: CBM_ARRAY(cbm,(rule_id >> CBM_SHIFT)) &= ~(1 << (rule_id & (CBM_SIZE-1)));
64: }
65:
66: /* Returns TRUE if bit corresponding to a rule number in a CBM is set */
67: static inline int cbm_check_rule(cbm_array_t *cbm,int rule_id)
68: {
69: return(CBM_ARRAY(cbm,(rule_id >> CBM_SHIFT)) &
70: (1 << (rule_id & (CBM_SIZE-1))));
71: }
72:
73: /* Compute bitwise ANDing of two CBM */
74: static inline void
75: cbm_bitwise_and(cbm_array_t *result,cbm_array_t *a1,cbm_array_t *a2)
76: {
77: int i;
78:
79: /* Compute bitwise ANDing */
80: for(i=0;i<a1->nr_entries;i++)
81: CBM_ARRAY(result,i) = CBM_ARRAY(a1,i) & CBM_ARRAY(a2,i);
82: }
83:
84: /* Get first matching rule number */
85: static inline int cbm_first_match(insn_lookup_t *ilt,cbm_array_t *cbm)
86: {
87: int i;
88:
89: for(i=0;i<ilt->nr_insn;i++)
90: if (cbm_check_rule(cbm,i))
91: return(i);
92:
93: return(-1);
94: }
95:
96: /* Create a class bitmap (CBM) */
97: static cbm_array_t *cbm_create(insn_lookup_t *ilt)
98: {
99: cbm_array_t *array;
100: int size;
101:
102: size = CBM_CSIZE(ilt->cbm_size);
103:
104: /* CBM are simply bit arrays */
105: assert((array = malloc(size)) != NULL);
106: memset(array,0,size);
107: array->nr_entries = ilt->cbm_size;
108: return array;
109: }
110:
111: /* Duplicate a class bitmap */
112: static cbm_array_t *cbm_duplicate(cbm_array_t *cbm)
113: {
114: int size = CBM_CSIZE(cbm->nr_entries);
115: cbm_array_t *array;
116:
117: assert((array = malloc(size)) != NULL);
118: memcpy(array,cbm,size);
119: return array;
120: }
121:
122: /*
123: * Get equivalent class corresponding to a class bitmap. Create eqclass
124: * structure if needed (CBM not previously seen).
125: */
126: static rfc_eqclass_t *cbm_get_eqclass(rfc_array_t *rfct,cbm_array_t *cbm)
127: {
128: rfc_eqclass_t *eqcl;
129: cbm_array_t *bmp;
130:
131: /* Lookup for CBM into hash table */
132: if ((eqcl = hash_table_lookup(rfct->cbm_hash,cbm)) == NULL)
133: {
134: /* Duplicate CBM */
135: assert((bmp = cbm_duplicate(cbm)) != NULL);
136:
137: /* CBM is not already known */
138: assert((eqcl = malloc(sizeof(rfc_eqclass_t))) != NULL);
139: assert(rfct->nr_eqid < rfct->nr_elements);
140:
141: /* Get a new equivalent ID */
142: eqcl->eqID = rfct->nr_eqid++;
143: eqcl->cbm = bmp;
144: rfct->id2cbm[eqcl->eqID] = bmp;
145:
146: /* Insert it in hash table */
147: assert(hash_table_insert(rfct->cbm_hash,bmp,eqcl) == 0);
148: }
149:
150: return eqcl;
151: }
152:
153: /* Allocate an array for Recursive Flow Classification */
154: static rfc_array_t *rfc_alloc_array(int nr_elements)
155: {
156: rfc_array_t *array;
157: int total_size;
158:
159: /* Compute size of memory chunk needed to store the array */
160: total_size = (nr_elements * sizeof(int)) + sizeof(rfc_array_t);
161: assert((array = malloc(total_size)) != NULL);
162:
163: memset(array,0,total_size);
164: array->nr_elements = nr_elements;
165:
166: /* Initialize hash table for Class Bitmaps */
167: array->cbm_hash = hash_table_create(cbm_hash_f,cbm_cmp_f,CBM_HASH_SIZE);
168: assert(array->cbm_hash != NULL);
169:
170: /* Initialize table for converting ID to CBM */
171: array->id2cbm = calloc(nr_elements,sizeof(cbm_array_t *));
172: assert(array->id2cbm != NULL);
173:
174: return(array);
175: }
176:
177: /* Check an instruction with specified parameter */
178: static void rfc_check_insn(insn_lookup_t *ilt,cbm_array_t *cbm,
179: ilt_check_cbk_t pcheck,int value)
180: {
181: void *p;
182: int i;
183:
184: for(i=0;i<ilt->nr_insn;i++) {
185: p = ilt->get_insn(i);
186:
187: if (pcheck(p,value))
188: cbm_set_rule(cbm,i);
189: else
190: cbm_unset_rule(cbm,i);
191: }
192: }
193:
194: /* RFC Chunk preprocessing: phase 0 */
195: static rfc_array_t *rfc_phase_0(insn_lookup_t *ilt,ilt_check_cbk_t pcheck)
196: {
197: rfc_eqclass_t *eqcl;
198: rfc_array_t *rfct;
199: cbm_array_t *bmp;
200: int i;
201:
202: /* allocate a temporary class bitmap */
203: assert((bmp = cbm_create(ilt)) != NULL);
204:
205: /* Allocate a new RFC array of 16-bits entries */
206: assert((rfct = rfc_alloc_array(RFC_ARRAY_MAXSIZE)) != NULL);
207:
208: for(i=0;i<RFC_ARRAY_MAXSIZE;i++)
209: {
210: /* determine all instructions that match this value */
211: rfc_check_insn(ilt,bmp,pcheck,i);
212:
213: /* get equivalent class for this bitmap */
214: assert((eqcl = cbm_get_eqclass(rfct,bmp)) != NULL);
215:
216: /* fill the RFC table */
217: rfct->eqID[i] = eqcl->eqID;
218: }
219:
220: free(bmp);
221: return rfct;
222: }
223:
224: /* RFC Chunk preprocessing: phase j (j > 0) */
225: static rfc_array_t *rfc_phase_j(insn_lookup_t *ilt,rfc_array_t *p0,
226: rfc_array_t *p1)
227: {
228: rfc_eqclass_t *eqcl;
229: rfc_array_t *rfct;
230: cbm_array_t *bmp;
231: int nr_elements;
232: int index = 0;
233: int i,j;
234:
235: /* allocate a temporary class bitmap */
236: assert((bmp = cbm_create(ilt)) != NULL);
237:
238: /* compute number of elements */
239: nr_elements = p0->nr_eqid * p1->nr_eqid;
240:
241: /* allocate a new RFC array */
242: assert((rfct = rfc_alloc_array(nr_elements)) != NULL);
243: rfct->parent0 = p0;
244: rfct->parent1 = p1;
245:
246: /* make a cross product between p0 and p1 */
247: for(i=0;i<p0->nr_eqid;i++)
248: for(j=0;j<p1->nr_eqid;j++)
249: {
250: /* compute bitwise AND */
251: cbm_bitwise_and(bmp,p0->id2cbm[i],p1->id2cbm[j]);
252:
253: /* get equivalent class for this bitmap */
254: assert((eqcl = cbm_get_eqclass(rfct,bmp)) != NULL);
255:
256: /* fill RFC table */
257: rfct->eqID[index++] = eqcl->eqID;
258: }
259:
260: free(bmp);
261: return rfct;
262: }
263:
264: /* Compute RFC phase 0 */
265: static void ilt_phase_0(insn_lookup_t *ilt,int idx,ilt_check_cbk_t pcheck)
266: {
267: rfc_array_t *rfct;
268:
269: assert((rfct = rfc_phase_0(ilt,pcheck)) != NULL);
270: ilt->rfct[idx] = rfct;
271: }
272:
273: /* Compute RFC phase j */
274: static void ilt_phase_j(insn_lookup_t *ilt,int p0,int p1,int res)
275: {
276: rfc_array_t *rfct;
277:
278: assert((rfct = rfc_phase_j(ilt,ilt->rfct[p0],ilt->rfct[p1])) != NULL);
279: ilt->rfct[res] = rfct;
280: }
281:
282: /* Postprocessing */
283: static void ilt_postprocessing(insn_lookup_t *ilt)
284: {
285: rfc_array_t *rfct = ilt->rfct[2];
286: int i;
287:
288: for(i=0;i<rfct->nr_elements;i++)
289: rfct->eqID[i] = cbm_first_match(ilt,rfct->id2cbm[rfct->eqID[i]]);
290: }
291:
292: /* Instruction lookup table compilation */
293: static void ilt_compile(insn_lookup_t *ilt)
294: {
295: ilt_phase_0(ilt,0,ilt->chk_hi);
296: ilt_phase_0(ilt,1,ilt->chk_lo);
297: ilt_phase_j(ilt,0,1,2);
298: ilt_postprocessing(ilt);
299: }
300:
301: /* Create an instruction lookup table */
302: insn_lookup_t *ilt_create(int nr_insn,ilt_get_insn_cbk_t get_insn,
303: ilt_check_cbk_t chk_lo,ilt_check_cbk_t chk_hi)
304: {
305: insn_lookup_t *ilt;
306:
307: assert((ilt = malloc(sizeof(*ilt))) != NULL);
308: memset(ilt,0,sizeof(*ilt));
309:
310: ilt->cbm_size = normalize_size(nr_insn,CBM_SIZE,CBM_SHIFT);
311: ilt->nr_insn = nr_insn;
312: ilt->get_insn = get_insn;
313: ilt->chk_lo = chk_lo;
314: ilt->chk_hi = chk_hi;
315:
316: ilt_compile(ilt);
317: return(ilt);
318: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.