origen_sim 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3fa5d90e78e17efb1942f6da11e1af57944e4ae1
4
- data.tar.gz: 5ef919794ccbe8c54762dc87b1f461821ecdb031
3
+ metadata.gz: d43f5b6b5fbd5690d6102a112092e4faab826395
4
+ data.tar.gz: 556101429de33f89de0898a205b5484dc8112af1
5
5
  SHA512:
6
- metadata.gz: ba5ee81d6b23bc3ca5c910cf12c491938e87fb7cd1140142744cc4610f1058ac09c7196e9161291c852aaa3eb7e5516fdf5940463b4e7fb6a839e580bf1df022
7
- data.tar.gz: 8fccdf6043048f57802489a64631bb1e8c6b757cba3c909690dd4e96582b71cca2b96a85f87f168f63c9aceff60ae62dfab5976af42ae4543b890b809dbed2e1
6
+ metadata.gz: baaf314cedd9d9af37b8ee73da872f35381651ad906fbd2607ac55650a04169e8eb04ce61c09bb64621425538e5e0c6dc760d302d5c8214a837d21b4cef6d70a
7
+ data.tar.gz: 740dcff5b5b89ecf3e41e7e872b6533757c7ee7834bb5cbd73454add475159ee70e2bc8e5962aaef9839b371ade03fc7fab46ca7301e46b846e0b0ef6f33c5a2
@@ -1,7 +1,7 @@
1
1
  module OrigenSim
2
2
  MAJOR = 0
3
3
  MINOR = 5
4
- BUGFIX = 0
4
+ BUGFIX = 1
5
5
  DEV = nil
6
6
 
7
7
  VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
@@ -0,0 +1,2 @@
1
+ This C library gets included into the Verilog testbench and controls the simulation based on instructions
2
+ from Ruby.
@@ -0,0 +1,790 @@
1
+ ///
2
+ /// This implements the bridge between Origen and the simulation, it implements a
3
+ /// simple string-based message protocol for communicating between the two domains
4
+ ///
5
+ #include "bridge.h"
6
+ #include "client.h"
7
+ #include <stdint.h>
8
+ #include <stdlib.h>
9
+ #include <stdio.h>
10
+ #include <stdbool.h>
11
+ #include <string.h>
12
+
13
+ #define MAX_NUMBER_PINS 2000
14
+ #define MAX_WAVE_EVENTS 10
15
+
16
+ typedef struct Pin {
17
+ vpiHandle data; // A handle to the driver data register
18
+ vpiHandle drive; // A handle to the driver drive enable register
19
+ vpiHandle force_data; // A handle to the driver force_data register
20
+ vpiHandle compare; // A handle to the driver compare enable register
21
+ vpiHandle capture; // A handle to the driver capture enable register
22
+ int drive_wave; // Index of the drive wave to be used for this pin
23
+ int compare_wave; // Index of the compare wave to be used for this pin
24
+ int drive_wave_pos; // Position of the pin in the drive_wave's active pin array
25
+ int compare_wave_pos; // Position of the pin in the compare_wave's active pin array
26
+ int index; // The pin's index in the pins array
27
+ int previous_state; // Used to keep track of whether the pin was previously driving or comparing
28
+ bool capture_en; // Used to indicated when compare data should be captured instead of compared
29
+ } Pin;
30
+
31
+ typedef struct Event {
32
+ int time;
33
+ char data;
34
+ } Event;
35
+
36
+ typedef struct Wave {
37
+ Event events[MAX_WAVE_EVENTS];
38
+ Pin *active_pins[MAX_NUMBER_PINS];
39
+ int active_pin_count;
40
+ } Wave;
41
+
42
+ static int period_in_ns;
43
+ static long repeat = 0;
44
+ static Pin pins[MAX_NUMBER_PINS];
45
+ static int number_of_pins = 0;
46
+ // Allocate space for a unique wave for each pin, in reality it will be much less
47
+ static Wave drive_waves[MAX_NUMBER_PINS];
48
+ static int number_of_drive_waves = 0;
49
+ static Wave compare_waves[MAX_NUMBER_PINS];
50
+ static int number_of_compare_waves = 0;
51
+ static int runtime_errors = 0;
52
+ static int log_messages = 0;
53
+
54
+ static void bridge_set_period(char*);
55
+ static void bridge_define_pin(char*, char*, char*, char*);
56
+ static void bridge_define_wave(char*, char*, char*);
57
+ static void bridge_cycle(void);
58
+ static void bridge_drive_pin(char*, char*);
59
+ static void bridge_compare_pin(char*, char*);
60
+ static void bridge_capture_pin(char*);
61
+ static void bridge_stop_capture_pin(char*);
62
+ static void bridge_dont_care_pin(char*);
63
+ static void bridge_register_wave_events(void);
64
+ static void bridge_register_wave_event(int, int, int, int);
65
+ static void bridge_enable_drive_wave(Pin*);
66
+ static void bridge_disable_drive_wave(Pin*);
67
+ static void bridge_enable_compare_wave(Pin*);
68
+ static void bridge_disable_compare_wave(Pin*);
69
+ static void bridge_clear_waves_and_pins(void);
70
+ static bool bridge_is_drive_whole_cycle(Pin*);
71
+ static void end_simulation(void);
72
+
73
+ static void bridge_define_pin(char * name, char * pin_ix, char * drive_wave_ix, char * compare_wave_ix) {
74
+ int index = atoi(pin_ix);
75
+ Pin *pin = &pins[index];
76
+ number_of_pins += 1;
77
+
78
+ (*pin).index = index;
79
+ (*pin).drive_wave = atoi(drive_wave_ix);
80
+ (*pin).compare_wave = atoi(compare_wave_ix);
81
+ (*pin).previous_state = 0;
82
+ (*pin).capture_en = false;
83
+
84
+ char * driver = (char *) malloc(strlen(name) + 16);
85
+ strcpy(driver, "origen.pins.");
86
+ strcat(driver, name);
87
+
88
+ char * data = (char *) malloc(strlen(driver) + 16);
89
+ strcpy(data, driver);
90
+ strcat(data, ".data");
91
+ (*pin).data = vpi_handle_by_name(data, NULL);
92
+ free(data);
93
+
94
+ char * drive = (char *) malloc(strlen(driver) + 16);
95
+ strcpy(drive, driver);
96
+ strcat(drive, ".drive");
97
+ (*pin).drive = vpi_handle_by_name(drive, NULL);
98
+ free(drive);
99
+
100
+ char * force = (char *) malloc(strlen(driver) + 16);
101
+ strcpy(force, driver);
102
+ strcat(force, ".force_data");
103
+ (*pin).force_data = vpi_handle_by_name(force, NULL);
104
+ free(force);
105
+
106
+ char * compare = (char *) malloc(strlen(driver) + 16);
107
+ strcpy(compare, driver);
108
+ strcat(compare, ".compare");
109
+ (*pin).compare = vpi_handle_by_name(compare, NULL);
110
+ free(compare);
111
+
112
+ char * capture = (char *) malloc(strlen(driver) + 16);
113
+ strcpy(capture, driver);
114
+ strcat(capture, ".capture");
115
+ (*pin).capture = vpi_handle_by_name(capture, NULL);
116
+ free(capture);
117
+
118
+ free(driver);
119
+ }
120
+
121
+
122
+ static void bridge_define_wave(char * index, char * compare, char * events) {
123
+ int ix = atoi(index);
124
+ Wave * wave;
125
+
126
+ if (compare[0] == '0') {
127
+ wave = &drive_waves[ix];
128
+ number_of_drive_waves += 1;
129
+ } else {
130
+ wave = &compare_waves[ix];
131
+ number_of_compare_waves += 1;
132
+ }
133
+
134
+ char * token;
135
+ // strtok needs a writable copy of events
136
+ char * myevents = (char *) malloc(strlen(events) + 1);
137
+ strcpy(myevents, events);
138
+
139
+ int i = 0;
140
+ token = strtok(myevents, "_");
141
+
142
+ while (token != NULL) {
143
+ (*wave).events[i].time = (int)strtol(token, NULL, 10);
144
+ token = strtok(NULL, "_");
145
+ (*wave).events[i].data = token[0];
146
+ token = strtok(NULL, "_");
147
+ i++;
148
+ }
149
+ (*wave).events[i].data = 'T'; // Indicate that there are no more events
150
+ free(myevents);
151
+ (*wave).active_pin_count = 0;
152
+ }
153
+
154
+
155
+ static void bridge_register_wave_events() {
156
+ for (int i = 0; i < number_of_drive_waves; i++) {
157
+
158
+ if (drive_waves[i].active_pin_count) {
159
+ int x = 0;
160
+
161
+ while (drive_waves[i].events[x].data != 'T' && x < MAX_WAVE_EVENTS) {
162
+ int time;
163
+
164
+ time = drive_waves[i].events[x].time;
165
+
166
+ // TODO: May save some time by calling directly at time 0
167
+ //if (time == 0) {
168
+ //} else {
169
+ bridge_register_wave_event(i, x, 0, time);
170
+ //}
171
+ x++;
172
+ }
173
+ }
174
+ }
175
+
176
+ for (int i = 0; i < number_of_compare_waves; i++) {
177
+
178
+ if (compare_waves[i].active_pin_count) {
179
+ int x = 0;
180
+
181
+ while (compare_waves[i].events[x].data != 'T' && x < MAX_WAVE_EVENTS) {
182
+ int time;
183
+
184
+ time = compare_waves[i].events[x].time;
185
+
186
+ // TODO: May save some time by calling directly at time 0
187
+ //if (time == 0) {
188
+ //} else {
189
+ bridge_register_wave_event(i, x, 1, time);
190
+ //}
191
+ x++;
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+
198
+ /// Enables the drive condition of the given pin.
199
+ /// This is done by adding the pin to the wave's active pin list, if the wave has
200
+ /// at least one pin in its list, the necessary callbacks will get triggered on every
201
+ /// cycle to implement the required waveform.
202
+ static void bridge_enable_drive_wave(Pin * pin) {
203
+ Wave *wave = &drive_waves[(*pin).drive_wave];
204
+
205
+ (*wave).active_pins[(*wave).active_pin_count] = pin;
206
+ (*pin).drive_wave_pos = (*wave).active_pin_count;
207
+ (*wave).active_pin_count += 1;
208
+ }
209
+
210
+
211
+ static void bridge_disable_drive_wave(Pin * pin) {
212
+ Wave *wave = &compare_waves[(*pin).drive_wave];
213
+
214
+ if ((*wave).active_pin_count == 0) {
215
+ vpi_printf("Wanted to disable drive on pin %i, but its drive wave has no active pins!\n", (*pin).index);
216
+ end_simulation();
217
+ }
218
+
219
+ // If pin is last, we can clear it by just decrementing the active pin counter
220
+ if ((*pin).drive_wave_pos != (*wave).active_pin_count - 1) {
221
+ // Otherwise we can remove it by overwriting it with the current last pin in the
222
+ // array, since the order is not important
223
+ (*wave).active_pins[(*pin).drive_wave_pos] = (*wave).active_pins[(*wave).active_pin_count - 1];
224
+ // Need to let the moved pin know its new position
225
+ (*(*wave).active_pins[(*pin).drive_wave_pos]).drive_wave_pos = (*pin).drive_wave_pos;
226
+ }
227
+
228
+ (*wave).active_pin_count -= 1;
229
+ }
230
+
231
+ static void bridge_enable_compare_wave(Pin * pin) {
232
+ Wave *wave = &compare_waves[(*pin).compare_wave];
233
+
234
+ (*wave).active_pins[(*wave).active_pin_count] = pin;
235
+ (*pin).compare_wave_pos = (*wave).active_pin_count;
236
+ (*wave).active_pin_count += 1;
237
+ }
238
+
239
+ static void bridge_disable_compare_wave(Pin * pin) {
240
+ Wave *wave = &compare_waves[(*pin).compare_wave];
241
+
242
+ // If pin is last, we can clear it by just decrementing the active pin counter
243
+ if ((*pin).compare_wave_pos != (*wave).active_pin_count - 1) {
244
+ // Otherwise we can remove it by overwriting it with the current last pin in the
245
+ // array, since the order is not important
246
+ (*wave).active_pins[(*pin).compare_wave_pos] = (*wave).active_pins[(*wave).active_pin_count - 1];
247
+ // Need to let the moved pin know its new position
248
+ (*(*wave).active_pins[(*pin).compare_wave_pos]).compare_wave_pos = (*pin).compare_wave_pos;
249
+ }
250
+
251
+ (*wave).active_pin_count -= 1;
252
+ }
253
+
254
+
255
+ static void bridge_clear_waves_and_pins() {
256
+ number_of_pins = 0;
257
+ number_of_drive_waves = 0;
258
+ number_of_compare_waves = 0;
259
+ }
260
+
261
+
262
+ static void bridge_set_period(char * p_in_ns) {
263
+ int p = (int) strtol(p_in_ns, NULL, 10);
264
+ period_in_ns = p;
265
+ bridge_clear_waves_and_pins();
266
+ }
267
+
268
+
269
+ static bool bridge_is_drive_whole_cycle(Pin * pin) {
270
+ Wave *wave = &drive_waves[(*pin).drive_wave];
271
+
272
+ // If drive wave only has one event
273
+ if ((*wave).events[1].data == 'T') {
274
+ // Return true if the single event specifies drive for the whole cycle
275
+ return (*wave).events[0].data == 'D' &&
276
+ (*wave).events[0].time == 0;
277
+ } else {
278
+ return false;
279
+ }
280
+ }
281
+
282
+
283
+ /// Immediately drives the given pin to the given value
284
+ static void bridge_drive_pin(char * index, char * val) {
285
+ Pin *pin = &pins[atoi(index)];
286
+ s_vpi_value v = {vpiIntVal, {0}};
287
+
288
+ // Apply the data value to the pin's driver
289
+ v.value.integer = (val[0] - '0');
290
+ vpi_put_value((*pin).data, &v, NULL, vpiNoDelay);
291
+ // Make sure not comparing
292
+ v.value.integer = 0;
293
+ vpi_put_value((*pin).compare, &v, NULL, vpiNoDelay);
294
+
295
+ // Register it as actively driving with it's wave
296
+
297
+ // If it is already driving the wave will already be setup
298
+ if ((*pin).previous_state != 1) {
299
+ // If the drive is for the whole cycle, then we can enable it here
300
+ // and don't need a callback
301
+ if (bridge_is_drive_whole_cycle(pin)) {
302
+ v.value.integer = 1;
303
+ vpi_put_value((*pin).drive, &v, NULL, vpiNoDelay);
304
+ } else {
305
+ bridge_enable_drive_wave(pin);
306
+ }
307
+
308
+ if ((*pin).previous_state == 2) {
309
+ bridge_disable_compare_wave(pin);
310
+ }
311
+ (*pin).previous_state = 1;
312
+ }
313
+ }
314
+
315
+
316
+ /// Immediately sets the given pin to compare against the given value
317
+ static void bridge_compare_pin(char * index, char * val) {
318
+ Pin *pin = &pins[atoi(index)];
319
+ s_vpi_value v = {vpiIntVal, {0}};
320
+
321
+ // Apply the data value to the pin's driver, don't enable compare yet,
322
+ // the wave will do that later
323
+ v.value.integer = (val[0] - '0');
324
+ vpi_put_value((*pin).data, &v, NULL, vpiNoDelay);
325
+ // Make sure not driving
326
+ v.value.integer = 0;
327
+ vpi_put_value((*pin).drive, &v, NULL, vpiNoDelay);
328
+
329
+ // Register it as actively comparing with it's wave
330
+
331
+ // If it is already comparing the wave will already be setup
332
+ if ((*pin).previous_state != 2) {
333
+ bridge_enable_compare_wave(pin);
334
+ if ((*pin).previous_state == 1) {
335
+ bridge_disable_drive_wave(pin);
336
+ }
337
+ (*pin).previous_state = 2;
338
+ }
339
+ }
340
+
341
+
342
+ /// Immediately sets the given pin to capture by registering it for compare
343
+ /// but with its capture flag set
344
+ static void bridge_capture_pin(char * index) {
345
+ Pin *pin = &pins[atoi(index)];
346
+ (*pin).capture_en = true;
347
+ bridge_compare_pin(index, "0");
348
+ }
349
+
350
+
351
+ /// Immediately sets the given pin to stop capture by clearing its capture flag
352
+ static void bridge_stop_capture_pin(char * index) {
353
+ Pin *pin = &pins[atoi(index)];
354
+ (*pin).capture_en = false;
355
+ }
356
+
357
+
358
+ /// Immediately sets the given pin to don't compare
359
+ static void bridge_dont_care_pin(char * index) {
360
+ Pin *pin = &pins[atoi(index)];
361
+ s_vpi_value v = {vpiIntVal, {0}};
362
+
363
+ // Disable drive and compare on the pin's driver
364
+ v.value.integer = 0;
365
+ vpi_put_value((*pin).drive, &v, NULL, vpiNoDelay);
366
+ vpi_put_value((*pin).compare, &v, NULL, vpiNoDelay);
367
+
368
+ if ((*pin).previous_state != 0) {
369
+ if ((*pin).previous_state == 1) {
370
+ if (!bridge_is_drive_whole_cycle(pin)) {
371
+ bridge_disable_drive_wave(pin);
372
+ }
373
+ }
374
+ if ((*pin).previous_state == 2) {
375
+ bridge_disable_compare_wave(pin);
376
+ }
377
+ (*pin).previous_state = 0;
378
+ }
379
+ }
380
+
381
+
382
+ /// Callback handler to implement the events registered by bridge_register_wave_event
383
+ PLI_INT32 bridge_apply_wave_event_cb(p_cb_data data) {
384
+ s_vpi_value v = {vpiIntVal, {0}};
385
+ s_vpi_value v2 = {vpiIntVal, {0}};
386
+
387
+ int * wave_ix = (int*)(&(data->user_data[0]));
388
+ int * event_ix = (int*)(&(data->user_data[sizeof(int)]));
389
+ int * compare = (int*)(&(data->user_data[sizeof(int) * 2]));
390
+
391
+ Wave * wave;
392
+
393
+ if (*compare) {
394
+ wave = &compare_waves[*wave_ix];
395
+
396
+ int d;
397
+ switch((*wave).events[*event_ix].data) {
398
+ case 'C' :
399
+ d = 1;
400
+ break;
401
+ case 'X' :
402
+ d = 0;
403
+ break;
404
+ default :
405
+ vpi_printf("ERROR: Unknown compare event: %c\n", (*wave).events[*event_ix].data);
406
+ runtime_errors += 1;
407
+ end_simulation();
408
+ return 1;
409
+ }
410
+
411
+ v.value.integer = d;
412
+ for (int i = 0; i < (*wave).active_pin_count; i++) {
413
+ if ((*(*wave).active_pins[i]).capture_en) {
414
+ vpi_put_value((*(*wave).active_pins[i]).capture, &v, NULL, vpiNoDelay);
415
+ } else {
416
+ vpi_put_value((*(*wave).active_pins[i]).compare, &v, NULL, vpiNoDelay);
417
+ }
418
+ }
419
+
420
+
421
+ } else {
422
+
423
+ wave = &drive_waves[*wave_ix];
424
+
425
+ //vpi_printf("[DEBUG] Apply drive wave %i, event %i, data %c\n", *wave_ix, *event_ix, (*wave).events[*event_ix].data);
426
+
427
+ int d;
428
+ int on;
429
+ switch((*wave).events[*event_ix].data) {
430
+ case '0' :
431
+ d = 1;
432
+ on = 1;
433
+ break;
434
+ case '1' :
435
+ d = 2;
436
+ on = 1;
437
+ break;
438
+ case 'D' :
439
+ d = 0;
440
+ on = 1;
441
+ break;
442
+ case 'X' :
443
+ d = 0;
444
+ on = 0;
445
+ break;
446
+ default :
447
+ vpi_printf("ERROR: Unknown drive event: %c\n", (*wave).events[*event_ix].data);
448
+ runtime_errors += 1;
449
+ end_simulation();
450
+ return 1;
451
+ }
452
+
453
+ v.value.integer = d;
454
+ v2.value.integer = on;
455
+ if (on) {
456
+ for (int i = 0; i < (*wave).active_pin_count; i++) {
457
+ vpi_put_value((*(*wave).active_pins[i]).force_data, &v, NULL, vpiNoDelay);
458
+ vpi_put_value((*(*wave).active_pins[i]).drive, &v2, NULL, vpiNoDelay);
459
+ }
460
+ } else {
461
+ for (int i = 0; i < (*wave).active_pin_count; i++) {
462
+ vpi_put_value((*(*wave).active_pins[i]).drive, &v2, NULL, vpiNoDelay);
463
+ }
464
+ }
465
+ }
466
+
467
+ free(data->user_data);
468
+
469
+ return 0;
470
+ }
471
+
472
+
473
+ /// Registers a callback to apply the given wave during this cycle
474
+ static void bridge_register_wave_event(int wave_ix, int event_ix, int compare, int delay_in_ns) {
475
+ s_cb_data call;
476
+ s_vpi_time time;
477
+
478
+ // This will get freed by the callback
479
+ char * user_data = (char *) malloc((sizeof(int) * 3));
480
+
481
+ int * d0 = (int*)(&user_data[0]);
482
+ int * d1 = (int*)(&user_data[sizeof(int)]);
483
+ int * d2 = (int*)(&user_data[sizeof(int) * 2]);
484
+
485
+ *d0 = wave_ix;
486
+ *d1 = event_ix;
487
+ *d2 = compare;
488
+
489
+ time.type = vpiSimTime;
490
+ time.high = (uint32_t)(0);
491
+ time.low = (uint32_t)(delay_in_ns);
492
+
493
+ call.reason = cbAfterDelay;
494
+ call.cb_rtn = bridge_apply_wave_event_cb;
495
+ call.obj = 0;
496
+ call.time = &time;
497
+ call.value = 0;
498
+ call.user_data = user_data;
499
+
500
+ vpi_free_object(vpi_register_cb(&call));
501
+ }
502
+
503
+
504
+ /// Entry point to the bridge_wait_for_msg loop
505
+ PLI_INT32 bridge_init() {
506
+ client_put("READY!\n");
507
+ return bridge_wait_for_msg(NULL);
508
+ }
509
+
510
+
511
+ /// Waits and responds to instructions from Origen (to set pin states).
512
+ /// When Origen requests a cycle, time will be advanced and this func will be called again.
513
+ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
514
+ UNUSED(data);
515
+ int max_msg_len = 100;
516
+ char msg[max_msg_len];
517
+ int err;
518
+ char *opcode, *arg1, *arg2, *arg3, *arg4;
519
+ vpiHandle handle;
520
+ s_vpi_value v;
521
+
522
+ while(1) {
523
+
524
+ err = client_get(max_msg_len, msg);
525
+ if (err) {
526
+ vpi_printf("ERROR: Failed to receive from Origen!\n");
527
+ end_simulation();
528
+ return 1;
529
+ }
530
+ if (runtime_errors) {
531
+ end_simulation();
532
+ return 1;
533
+ }
534
+
535
+ if (log_messages) {
536
+ vpi_printf("[MESSAGE] %s\n", msg);
537
+ }
538
+
539
+ // Keep a copy of the original message, helpful for debugging
540
+ char* orig_msg = calloc(strlen(msg)+1, sizeof(char));
541
+ strcpy(orig_msg, msg);
542
+
543
+ opcode = strtok(msg, "^");
544
+
545
+ switch(*opcode) {
546
+ // Define pin
547
+ // 0^pin_name^pin_index^drive_wave_ix^capture_wave_ix
548
+ //
549
+ // 0 for the wave indexes means the default, custom waves
550
+ // must therefore start from index 1
551
+ //
552
+ // The pin index must be uniquely assigned to the pin by the caller
553
+ // and must be less than MAX_NUMBER_PINS
554
+ //
555
+ // 0^tdi^12^0^0
556
+ case '0' :
557
+ arg1 = strtok(NULL, "^");
558
+ arg2 = strtok(NULL, "^");
559
+ arg3 = strtok(NULL, "^");
560
+ arg4 = strtok(NULL, "^");
561
+ //DEBUG("Define Pin: %s, %s, %s, %s\n", arg1, arg2, arg3, arg4);
562
+ bridge_define_pin(arg1, arg2, arg3, arg4);
563
+ break;
564
+ // Set Period
565
+ // 1^100
566
+ case '1' :
567
+ arg1 = strtok(NULL, "^");
568
+ bridge_set_period(arg1);
569
+ break;
570
+ // Drive Pin
571
+ // 2^pin_index^data
572
+ //
573
+ // 2^12^0
574
+ // 2^12^1
575
+ case '2' :
576
+ arg1 = strtok(NULL, "^");
577
+ arg2 = strtok(NULL, "^");
578
+ //DEBUG("Drive Pin: %s, %s\n", arg1, arg2);
579
+ bridge_drive_pin(arg1, arg2);
580
+ break;
581
+ // Cycle
582
+ // 3^number_of_cycles
583
+ //
584
+ // 3^1
585
+ // 3^65535
586
+ case '3' :
587
+ arg1 = strtok(NULL, "^");
588
+ repeat = strtol(arg1, NULL, 10);
589
+ if (repeat) {
590
+ repeat = repeat - 1;
591
+ }
592
+ bridge_cycle();
593
+ return 0;
594
+ // Compare Pin
595
+ // 4^pin_index^data
596
+ //
597
+ // 4^14^0
598
+ // 4^14^1
599
+ case '4' :
600
+ arg1 = strtok(NULL, "^");
601
+ arg2 = strtok(NULL, "^");
602
+ bridge_compare_pin(arg1, arg2);
603
+ break;
604
+ // Don't Care Pin
605
+ // 5^pin_index
606
+ //
607
+ // 5^14
608
+ case '5' :
609
+ arg1 = strtok(NULL, "^");
610
+ bridge_dont_care_pin(arg1);
611
+ break;
612
+ // Define wave
613
+ // 6^wave_index^compare^events
614
+ //
615
+ // 0 for the wave indexes means the default, custom waves
616
+ // must therefore start from index 1
617
+ //
618
+ // 0 for the compare parameter means it is a drive wave, 1 means it is
619
+ // for when the pin is in compare mode
620
+ //
621
+ // Some example events are shown below:
622
+ //
623
+ // 6^1^0^0_D_25_0_50_D_75_0 // Drive at 0ns, off at 25ns, drive at 50ns, off at 75ns
624
+ case '6' :
625
+ arg1 = strtok(NULL, "^");
626
+ arg2 = strtok(NULL, "^");
627
+ arg3 = strtok(NULL, "^");
628
+ //DEBUG("Define Wave: %s, %s, %s\n", arg1, arg2, arg3);
629
+ bridge_define_wave(arg1, arg2, arg3);
630
+ break;
631
+ // Sync-up
632
+ // 7^
633
+ case '7' :
634
+ client_put("OK!\n");
635
+ break;
636
+ // Complete
637
+ // 8^
638
+ case '8' :
639
+ end_simulation();
640
+ return 0;
641
+ // Peek
642
+ // Returns the current value of the given net
643
+ //
644
+ // 9^origen.debug.errors
645
+ case '9' :
646
+ arg1 = strtok(NULL, "^");
647
+ handle = vpi_handle_by_name(arg1, NULL);
648
+ if (handle) {
649
+ v.format = vpiDecStrVal; // Seems important to set this before get
650
+ vpi_get_value(handle, &v);
651
+ sprintf(msg, "%s\n", v.value.str);
652
+ client_put(msg);
653
+ } else {
654
+ client_put("FAIL\n");
655
+ }
656
+ break;
657
+ // Set Pattern Name
658
+ // a^atd_ramp_25mhz
659
+ case 'a' :
660
+ handle = vpi_handle_by_name("origen.debug.pattern", NULL);
661
+ arg1 = strtok(NULL, "^");
662
+
663
+ v.format = vpiStringVal;
664
+ v.value.str = arg1;
665
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
666
+ break;
667
+ // Poke
668
+ // Sets the given value on the given net, the number should be
669
+ // given as a decimal string
670
+ //
671
+ // b^origen.debug.errors^15
672
+ case 'b' :
673
+ arg1 = strtok(NULL, "^");
674
+ arg2 = strtok(NULL, "^");
675
+ handle = vpi_handle_by_name(arg1, NULL);
676
+ if (handle) {
677
+ v.format = vpiDecStrVal;
678
+ v.value.str = arg2;
679
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
680
+ }
681
+ break;
682
+ // Set Comment
683
+ // c^Some comment about the pattern
684
+ case 'c' :
685
+ handle = vpi_handle_by_name("origen.debug.comments", NULL);
686
+ arg1 = strtok(NULL, "^");
687
+
688
+ v.format = vpiStringVal;
689
+ v.value.str = arg1;
690
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
691
+ break;
692
+ // Log all messages
693
+ // d^1 Turn logging on
694
+ // d^0 Turn logging off
695
+ case 'd' :
696
+ arg1 = strtok(NULL, "^");
697
+ log_messages = atoi(arg1);
698
+ break;
699
+ // Capture Pin
700
+ // e^pin_index
701
+ //
702
+ // e^14
703
+ case 'e' :
704
+ arg1 = strtok(NULL, "^");
705
+ bridge_capture_pin(arg1);
706
+ break;
707
+ // Sync enable
708
+ case 'f' :
709
+ handle = vpi_handle_by_name("origen.pins.sync", NULL);
710
+ v.format = vpiDecStrVal;
711
+ v.value.str = "1";
712
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
713
+ break;
714
+ // Sync disable
715
+ case 'g' :
716
+ handle = vpi_handle_by_name("origen.pins.sync", NULL);
717
+ v.format = vpiDecStrVal;
718
+ v.value.str = "0";
719
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
720
+ break;
721
+ // Stop Capture Pin
722
+ // h^pin_index
723
+ //
724
+ // h^14
725
+ case 'h' :
726
+ arg1 = strtok(NULL, "^");
727
+ bridge_stop_capture_pin(arg1);
728
+ break;
729
+ default :
730
+ vpi_printf("ERROR: Illegal message received from Origen: %s\n", orig_msg);
731
+ runtime_errors += 1;
732
+ end_simulation();
733
+ return 1;
734
+ }
735
+ free(orig_msg);
736
+ }
737
+ }
738
+
739
+
740
+ static void end_simulation() {
741
+ vpiHandle handle;
742
+ s_vpi_value v;
743
+
744
+ // Setting this node will cause the testbench to call $finish
745
+ handle = vpi_handle_by_name("origen.finish", NULL);
746
+ v.format = vpiDecStrVal;
747
+ v.value.str = "1";
748
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
749
+ // Corner case during testing, the timeset may not have been set yet
750
+ bridge_set_period("1");
751
+ // Do a cycle so that the simulation sees the edge on origen.finish
752
+ bridge_cycle();
753
+ }
754
+
755
+
756
+ PLI_INT32 bridge_cycle_cb(p_cb_data data) {
757
+ UNUSED(data);
758
+ repeat = repeat - 1;
759
+ bridge_cycle();
760
+ return 0;
761
+ }
762
+
763
+
764
+ /// Registers a callback after a cycle period, the main server loop should unblock
765
+ /// after calling this to allow the simulation to proceed for a cycle
766
+ static void bridge_cycle() {
767
+ s_cb_data call;
768
+ s_vpi_time time;
769
+
770
+ time.type = vpiSimTime;
771
+ time.high = (uint32_t)(0);
772
+ time.low = (uint32_t)(period_in_ns);
773
+
774
+ call.reason = cbAfterDelay;
775
+ call.obj = 0;
776
+ call.time = &time;
777
+ call.value = 0;
778
+ call.user_data = 0;
779
+
780
+ //DEBUG("REPEAT: %d\n", repeat);
781
+ if (repeat) {
782
+ call.cb_rtn = bridge_cycle_cb;
783
+ } else {
784
+ call.cb_rtn = bridge_wait_for_msg;
785
+ }
786
+
787
+ vpi_free_object(vpi_register_cb(&call));
788
+
789
+ bridge_register_wave_events();
790
+ }