origen_sim 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }