origen_sim 0.15.0 → 0.16.0

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
  SHA256:
3
- metadata.gz: a37dd737642a62e60b4cc98f47928b659004f3b89e771aa9efabfd2610622080
4
- data.tar.gz: 74309fc46e200d299e8704e4599fdd3553abd1cb380ec56a9c7d926f1a7728f7
3
+ metadata.gz: 43c4c9b46fca49ffc621f5fe6acc1e10c0961db6453c3a67f09e8bc2e0bc233f
4
+ data.tar.gz: bc825d94eb0859054fbfcd1cb7bbae4c980a8a1b356c489ecbfb2308f0b17697
5
5
  SHA512:
6
- metadata.gz: e94281aa75824657de8e4df717201db48d8b8fc02669b84b78e34f271533a119e88b6881a28d41ce6ecb5e2d12192d78d042764d6efabb2548e8c3fec7069080
7
- data.tar.gz: 0404e46a47d0d02d5933ed238fc84b6660f3cbae5f70d7c632c4ca2cb87c8ada52b8a2b382becf4e59b2c276a423890b569de6a227b6d31f329eee26ca66711f
6
+ metadata.gz: 731d4bf00e0f801b08063445a17373dc8d8f48162ed517db8fe154547e7c384e1bbb6b9ab4e4432fb995cc20bd840a0792dc3700e66b3a85cc92d1ee444cc910
7
+ data.tar.gz: f68c396143c15f87f210d6c94d2d5020bc07d21c2da3a8664b4e85f6c9fcd3c039e82b963e2d539d58d5bd46cd5b5670450f4f5615cb1359dad353d9f3b9a84d
@@ -42,7 +42,7 @@ class OrigenSimApplication < Origen::Application
42
42
  section.page :flows, heading: "Simulating Flows"
43
43
  section.page :log, heading: "Simulator Log Output"
44
44
  section.page :artifacts, heading: "Artifacts"
45
- section.page :debugging, heading: "Interactive Debugging"
45
+ section.page :debugging, heading: "Debugging"
46
46
  end
47
47
  end
48
48
  }
@@ -1,15 +1,20 @@
1
1
  # The requested command is passed in here as @command
2
2
  case @command
3
3
 
4
- when 'generate'
4
+ when 'generate', 'program'
5
5
  $use_fast_probe_depth = false
6
6
  @application_options << ["--fast", "Fast simulation, minimum probe depth"]
7
7
  $use_fast_probe_depth = ARGV.include?('--fast')
8
8
 
9
- @application_options << ["--sim_capture", "Update sim captures (ignored when not running a simulation)"]
10
- Origen.app!.update_sim_captures = ARGV.include?('--sim_capture')
9
+ @application_options << ["--sim_capture", "Update sim captures (ignored when not running a simulation)", ->(options) {
10
+ Origen.app!.update_sim_captures = true
11
+ }]
11
12
 
12
- @application_options << ["--flow NAME", "Simulate multiple patterns back-back within a single simulation with the given name", ->(options, name) { OrigenSim.flow = name }]
13
+ unless @command == 'program'
14
+ @application_options << ["--flow NAME", "Simulate multiple patterns back-back within a single simulation with the given name", ->(options, name) {
15
+ OrigenSim.flow = name
16
+ }]
17
+ end
13
18
 
14
19
  @application_options << ["--socket_dir PATH", "Specify the directory to be used for creating the Origen -> simulator communication socket (/tmp by default) ", ->(options, path) {
15
20
  FileUtils.mkdir_p(path) unless File.exist?(path)
@@ -18,6 +23,10 @@ when 'generate'
18
23
  OrigenSim.socket_dir = path
19
24
  }]
20
25
 
26
+ @application_options << ["--max_errors VALUE", Integer, "Override the maximum number of errors allowed in a simulation before aborting ", ->(options, value) {
27
+ OrigenSim.max_errors = value
28
+ }]
29
+
21
30
  when "sim:ci", "origen_sim:ci"
22
31
  require "#{Origen.root!}/lib/origen_sim/commands/ci"
23
32
  exit 0
data/config/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module OrigenSim
2
2
  MAJOR = 0
3
- MINOR = 15
3
+ MINOR = 16
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
data/ext/bridge.c CHANGED
@@ -10,9 +10,11 @@
10
10
  #include <stdio.h>
11
11
  #include <stdbool.h>
12
12
  #include <string.h>
13
+ #include <stdarg.h>
13
14
 
14
15
  #define MAX_NUMBER_PINS 2000
15
16
  #define MAX_WAVE_EVENTS 50
17
+ #define MAX_TRANSACTION_ERRORS 128
16
18
 
17
19
  typedef struct Pin {
18
20
  char *name;
@@ -42,8 +44,22 @@ typedef struct Wave {
42
44
  int active_pin_count;
43
45
  } Wave;
44
46
 
45
- static uint64_t period_in_ps;
46
- static long repeat = 0;
47
+ // Used to record a miscompare event that is used by OrigenSim to work out the actual data
48
+ // from a failed register read transaction
49
+ typedef struct Miscompare {
50
+ char *pin_name;
51
+ unsigned long long cycle;
52
+ int expected;
53
+ int received;
54
+ } Miscompare;
55
+
56
+ static Miscompare miscompares[MAX_TRANSACTION_ERRORS];
57
+ static int transaction_error_count = 0;
58
+ static bool transaction_open = false;
59
+ static int match_loop_error_count = 0;
60
+ static bool match_loop_open = false;
61
+ static uint64_t period_in_simtime_units;
62
+ static unsigned long repeat = 0;
47
63
  static Pin pins[MAX_NUMBER_PINS];
48
64
  static int number_of_pins = 0;
49
65
  // Allocate space for a unique wave for each pin, in reality it will be much less
@@ -53,27 +69,34 @@ static Wave compare_waves[MAX_NUMBER_PINS];
53
69
  static int number_of_compare_waves = 0;
54
70
  static int runtime_errors = 0;
55
71
  static int log_messages = 0;
56
-
57
- static void bridge_set_period(char*);
58
- static void bridge_define_pin(char*, char*, char*, char*);
59
- static void bridge_define_wave(char*, char*, char*);
60
- static void bridge_cycle(void);
61
- static void bridge_drive_pin(char*, char*);
62
- static void bridge_compare_pin(char*, char*);
63
- static void bridge_capture_pin(char*);
64
- static void bridge_stop_capture_pin(char*);
65
- static void bridge_dont_care_pin(char*);
66
- static void bridge_register_wave_events(void);
67
- static void bridge_register_wave_event(int, int, int, uint64_t);
68
- static void bridge_enable_drive_wave(Pin*);
69
- static void bridge_disable_drive_wave(Pin*);
70
- static void bridge_enable_compare_wave(Pin*);
71
- static void bridge_disable_compare_wave(Pin*);
72
- static void bridge_clear_waves_and_pins(void);
73
- static bool bridge_is_drive_whole_cycle(Pin*);
72
+ static int error_count = 0;
73
+ static int max_errors = 100;
74
+ static unsigned long long cycle_count = 0;
75
+ static bool max_errors_exceeded = false;
76
+ static bool max_errors_exceeded_during_transaction = false;
77
+
78
+ static void set_period(char*);
79
+ static void define_pin(char*, char*, char*, char*);
80
+ static void define_wave(char*, char*, char*);
81
+ static void cycle(void);
82
+ static void drive_pin(char*, char*);
83
+ static void compare_pin(char*, char*);
84
+ static void capture_pin(char*);
85
+ static void stop_capture_pin(char*);
86
+ static void dont_care_pin(char*);
87
+ static void register_wave_events(void);
88
+ static void register_wave_event(int, int, int, uint64_t);
89
+ static void enable_drive_wave(Pin*);
90
+ static void disable_drive_wave(Pin*);
91
+ static void enable_compare_wave(Pin*);
92
+ static void disable_compare_wave(Pin*);
93
+ static void clear_waves_and_pins(void);
94
+ static bool is_drive_whole_cycle(Pin*);
95
+ static void origen_log(int, const char*, ...);
74
96
  static void end_simulation(void);
97
+ static void on_max_errors_exceeded(void);
75
98
 
76
- static void bridge_define_pin(char * name, char * pin_ix, char * drive_wave_ix, char * compare_wave_ix) {
99
+ static void define_pin(char * name, char * pin_ix, char * drive_wave_ix, char * compare_wave_ix) {
77
100
  int index = atoi(pin_ix);
78
101
  Pin *pin = &pins[index];
79
102
  number_of_pins += 1;
@@ -98,7 +121,7 @@ static void bridge_define_pin(char * name, char * pin_ix, char * drive_wave_ix,
98
121
  free(data);
99
122
 
100
123
  if (!(*pin).data) {
101
- vpi_printf("WARNING: Your DUT defines pin '%s', however it is not present in the testbench and will be ignored\n", (*pin).name);
124
+ origen_log(LOG_WARNING, "Your DUT defines pin '%s', however it is not present in the testbench and will be ignored", (*pin).name);
102
125
  (*pin).present = false;
103
126
  } else {
104
127
  (*pin).present = true;
@@ -132,7 +155,7 @@ static void bridge_define_pin(char * name, char * pin_ix, char * drive_wave_ix,
132
155
  }
133
156
 
134
157
 
135
- static void bridge_define_wave(char * index, char * compare, char * events) {
158
+ static void define_wave(char * index, char * compare, char * events) {
136
159
  int ix = atoi(index);
137
160
  Wave * wave;
138
161
 
@@ -165,7 +188,7 @@ static void bridge_define_wave(char * index, char * compare, char * events) {
165
188
  }
166
189
 
167
190
 
168
- static void bridge_register_wave_events() {
191
+ static void register_wave_events() {
169
192
  for (int i = 0; i < number_of_drive_waves; i++) {
170
193
 
171
194
  if (drive_waves[i].active_pin_count) {
@@ -179,7 +202,7 @@ static void bridge_register_wave_events() {
179
202
  // TODO: May save some time by calling directly at time 0
180
203
  //if (time == 0) {
181
204
  //} else {
182
- bridge_register_wave_event(i, x, 0, time);
205
+ register_wave_event(i, x, 0, time);
183
206
  //}
184
207
  x++;
185
208
  }
@@ -199,7 +222,7 @@ static void bridge_register_wave_events() {
199
222
  // TODO: May save some time by calling directly at time 0
200
223
  //if (time == 0) {
201
224
  //} else {
202
- bridge_register_wave_event(i, x, 1, time);
225
+ register_wave_event(i, x, 1, time);
203
226
  //}
204
227
  x++;
205
228
  }
@@ -212,7 +235,7 @@ static void bridge_register_wave_events() {
212
235
  /// This is done by adding the pin to the wave's active pin list, if the wave has
213
236
  /// at least one pin in its list, the necessary callbacks will get triggered on every
214
237
  /// cycle to implement the required waveform.
215
- static void bridge_enable_drive_wave(Pin * pin) {
238
+ static void enable_drive_wave(Pin * pin) {
216
239
  Wave *wave = &drive_waves[(*pin).drive_wave];
217
240
 
218
241
  (*wave).active_pins[(*wave).active_pin_count] = pin;
@@ -221,11 +244,11 @@ static void bridge_enable_drive_wave(Pin * pin) {
221
244
  }
222
245
 
223
246
 
224
- static void bridge_disable_drive_wave(Pin * pin) {
247
+ static void disable_drive_wave(Pin * pin) {
225
248
  Wave *wave = &drive_waves[(*pin).drive_wave];
226
249
 
227
250
  if ((*wave).active_pin_count == 0) {
228
- vpi_printf("Wanted to disable drive on pin %i, but its drive wave has no active pins!\n", (*pin).index);
251
+ origen_log(LOG_ERROR, "Wanted to disable drive on pin %i, but its drive wave has no active pins!", (*pin).index);
229
252
  end_simulation();
230
253
  }
231
254
 
@@ -241,7 +264,7 @@ static void bridge_disable_drive_wave(Pin * pin) {
241
264
  (*wave).active_pin_count -= 1;
242
265
  }
243
266
 
244
- static void bridge_enable_compare_wave(Pin * pin) {
267
+ static void enable_compare_wave(Pin * pin) {
245
268
  Wave *wave = &compare_waves[(*pin).compare_wave];
246
269
 
247
270
  (*wave).active_pins[(*wave).active_pin_count] = pin;
@@ -249,7 +272,7 @@ static void bridge_enable_compare_wave(Pin * pin) {
249
272
  (*wave).active_pin_count += 1;
250
273
  }
251
274
 
252
- static void bridge_disable_compare_wave(Pin * pin) {
275
+ static void disable_compare_wave(Pin * pin) {
253
276
  Wave *wave = &compare_waves[(*pin).compare_wave];
254
277
 
255
278
  // If pin is last, we can clear it by just decrementing the active pin counter
@@ -265,7 +288,7 @@ static void bridge_disable_compare_wave(Pin * pin) {
265
288
  }
266
289
 
267
290
 
268
- static void bridge_clear_waves_and_pins() {
291
+ static void clear_waves_and_pins() {
269
292
  for (int i = 0; i < number_of_pins; i++) {
270
293
  Pin *pin = &pins[i];
271
294
  free((*pin).name);
@@ -276,14 +299,14 @@ static void bridge_clear_waves_and_pins() {
276
299
  }
277
300
 
278
301
 
279
- static void bridge_set_period(char * p_in_ps_str) {
280
- uint64_t p = (uint64_t) strtol(p_in_ps_str, NULL, 10);
281
- period_in_ps = p;
282
- bridge_clear_waves_and_pins();
302
+ static void set_period(char * p_in_simtime_units_str) {
303
+ uint64_t p = (uint64_t) strtol(p_in_simtime_units_str, NULL, 10);
304
+ period_in_simtime_units = p;
305
+ clear_waves_and_pins();
283
306
  }
284
307
 
285
308
 
286
- static bool bridge_is_drive_whole_cycle(Pin * pin) {
309
+ static bool is_drive_whole_cycle(Pin * pin) {
287
310
  Wave *wave = &drive_waves[(*pin).drive_wave];
288
311
 
289
312
  // If drive wave only has one event
@@ -298,7 +321,7 @@ static bool bridge_is_drive_whole_cycle(Pin * pin) {
298
321
 
299
322
 
300
323
  /// Immediately drives the given pin to the given value
301
- static void bridge_drive_pin(char * index, char * val) {
324
+ static void drive_pin(char * index, char * val) {
302
325
  Pin *pin = &pins[atoi(index)];
303
326
  s_vpi_value v = {vpiIntVal, {0}};
304
327
 
@@ -316,15 +339,15 @@ static void bridge_drive_pin(char * index, char * val) {
316
339
  if ((*pin).previous_state != 1) {
317
340
  // If the drive is for the whole cycle, then we can enable it here
318
341
  // and don't need a callback
319
- if (bridge_is_drive_whole_cycle(pin)) {
342
+ if (is_drive_whole_cycle(pin)) {
320
343
  v.value.integer = 1;
321
344
  vpi_put_value((*pin).drive, &v, NULL, vpiNoDelay);
322
345
  } else {
323
- bridge_enable_drive_wave(pin);
346
+ enable_drive_wave(pin);
324
347
  }
325
348
 
326
349
  if ((*pin).previous_state == 2) {
327
- bridge_disable_compare_wave(pin);
350
+ disable_compare_wave(pin);
328
351
  }
329
352
  (*pin).previous_state = 1;
330
353
  }
@@ -333,7 +356,7 @@ static void bridge_drive_pin(char * index, char * val) {
333
356
 
334
357
 
335
358
  /// Immediately sets the given pin to compare against the given value
336
- static void bridge_compare_pin(char * index, char * val) {
359
+ static void compare_pin(char * index, char * val) {
337
360
  Pin *pin = &pins[atoi(index)];
338
361
  s_vpi_value v = {vpiIntVal, {0}};
339
362
 
@@ -350,10 +373,10 @@ static void bridge_compare_pin(char * index, char * val) {
350
373
 
351
374
  // If it is already comparing the wave will already be setup
352
375
  if ((*pin).previous_state != 2) {
353
- bridge_enable_compare_wave(pin);
376
+ enable_compare_wave(pin);
354
377
  if ((*pin).previous_state == 1) {
355
- if (!bridge_is_drive_whole_cycle(pin)) {
356
- bridge_disable_drive_wave(pin);
378
+ if (!is_drive_whole_cycle(pin)) {
379
+ disable_drive_wave(pin);
357
380
  }
358
381
  }
359
382
  (*pin).previous_state = 2;
@@ -364,22 +387,22 @@ static void bridge_compare_pin(char * index, char * val) {
364
387
 
365
388
  /// Immediately sets the given pin to capture by registering it for compare
366
389
  /// but with its capture flag set
367
- static void bridge_capture_pin(char * index) {
390
+ static void capture_pin(char * index) {
368
391
  Pin *pin = &pins[atoi(index)];
369
392
  (*pin).capture_en = true;
370
- bridge_compare_pin(index, "0");
393
+ compare_pin(index, "0");
371
394
  }
372
395
 
373
396
 
374
397
  /// Immediately sets the given pin to stop capture by clearing its capture flag
375
- static void bridge_stop_capture_pin(char * index) {
398
+ static void stop_capture_pin(char * index) {
376
399
  Pin *pin = &pins[atoi(index)];
377
400
  (*pin).capture_en = false;
378
401
  }
379
402
 
380
403
 
381
404
  /// Immediately sets the given pin to don't compare
382
- static void bridge_dont_care_pin(char * index) {
405
+ static void dont_care_pin(char * index) {
383
406
  Pin *pin = &pins[atoi(index)];
384
407
  s_vpi_value v = {vpiIntVal, {0}};
385
408
 
@@ -391,12 +414,12 @@ static void bridge_dont_care_pin(char * index) {
391
414
 
392
415
  if ((*pin).previous_state != 0) {
393
416
  if ((*pin).previous_state == 1) {
394
- if (!bridge_is_drive_whole_cycle(pin)) {
395
- bridge_disable_drive_wave(pin);
417
+ if (!is_drive_whole_cycle(pin)) {
418
+ disable_drive_wave(pin);
396
419
  }
397
420
  }
398
421
  if ((*pin).previous_state == 2) {
399
- bridge_disable_compare_wave(pin);
422
+ disable_compare_wave(pin);
400
423
  }
401
424
  (*pin).previous_state = 0;
402
425
  }
@@ -404,8 +427,8 @@ static void bridge_dont_care_pin(char * index) {
404
427
  }
405
428
 
406
429
 
407
- /// Callback handler to implement the events registered by bridge_register_wave_event
408
- PLI_INT32 bridge_apply_wave_event_cb(p_cb_data data) {
430
+ /// Callback handler to implement the events registered by register_wave_event
431
+ PLI_INT32 apply_wave_event_cb(p_cb_data data) {
409
432
  s_vpi_value v = {vpiIntVal, {0}};
410
433
  s_vpi_value v2 = {vpiIntVal, {0}};
411
434
 
@@ -427,7 +450,7 @@ PLI_INT32 bridge_apply_wave_event_cb(p_cb_data data) {
427
450
  d = 0;
428
451
  break;
429
452
  default :
430
- vpi_printf("ERROR: Unknown compare event: %c\n", (*wave).events[*event_ix].data);
453
+ origen_log(LOG_ERROR, "Unknown compare event: %c", (*wave).events[*event_ix].data);
431
454
  runtime_errors += 1;
432
455
  end_simulation();
433
456
  return 1;
@@ -469,7 +492,7 @@ PLI_INT32 bridge_apply_wave_event_cb(p_cb_data data) {
469
492
  on = 0;
470
493
  break;
471
494
  default :
472
- vpi_printf("ERROR: Unknown drive event: %c\n", (*wave).events[*event_ix].data);
495
+ origen_log(LOG_ERROR, "Unknown drive event: %c\n", (*wave).events[*event_ix].data);
473
496
  runtime_errors += 1;
474
497
  end_simulation();
475
498
  return 1;
@@ -496,7 +519,7 @@ PLI_INT32 bridge_apply_wave_event_cb(p_cb_data data) {
496
519
 
497
520
 
498
521
  /// Registers a callback to apply the given wave during this cycle
499
- static void bridge_register_wave_event(int wave_ix, int event_ix, int compare, uint64_t delay_in_ps) {
522
+ static void register_wave_event(int wave_ix, int event_ix, int compare, uint64_t delay_in_simtime_units) {
500
523
  s_cb_data call;
501
524
  s_vpi_time time;
502
525
 
@@ -513,11 +536,11 @@ static void bridge_register_wave_event(int wave_ix, int event_ix, int compare, u
513
536
 
514
537
  time.type = vpiSimTime;
515
538
 
516
- time.high = (uint32_t)(delay_in_ps >> 32);
517
- time.low = (uint32_t)(delay_in_ps);
539
+ time.high = (uint32_t)(delay_in_simtime_units >> 32);
540
+ time.low = (uint32_t)(delay_in_simtime_units);
518
541
 
519
542
  call.reason = cbAfterDelay;
520
- call.cb_rtn = bridge_apply_wave_event_cb;
543
+ call.cb_rtn = apply_wave_event_cb;
521
544
  call.obj = 0;
522
545
  call.time = &time;
523
546
  call.value = 0;
@@ -534,6 +557,28 @@ PLI_INT32 bridge_init() {
534
557
  }
535
558
 
536
559
 
560
+ /// Send output to the Origen log, this will be automatically timestamped to the simulation and
561
+ /// sprintf type arguments can be supplied when calling:
562
+ ///
563
+ /// origen_log(LOG_ERROR, "Wanted to disable drive on pin %i, but its drive wave has no active pins!", (*pin).index);
564
+ /// origen_log(LOG_INFO, "Something to tell you about");
565
+ static void origen_log(int type, const char * fmt, ...) {
566
+ s_vpi_time now;
567
+ int max_msg_len = 2048;
568
+ char msg[max_msg_len];
569
+ va_list aptr;
570
+
571
+ now.type = vpiSimTime;
572
+ vpi_get_time(0, &now);
573
+
574
+ va_start(aptr, fmt);
575
+ vsprintf(msg, fmt, aptr);
576
+ va_end(aptr);
577
+
578
+ vpi_printf("!%d![%u,%u] %s\n", type, now.high, now.low, msg);
579
+ };
580
+
581
+
537
582
  /// Waits and responds to instructions from Origen (to set pin states).
538
583
  /// When Origen requests a cycle, time will be advanced and this func will be called again.
539
584
  PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
@@ -542,6 +587,8 @@ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
542
587
  char msg[max_msg_len];
543
588
  char comment[128];
544
589
  int err;
590
+ int timescale;
591
+ int type;
545
592
  char *opcode, *arg1, *arg2, *arg3, *arg4;
546
593
  vpiHandle handle;
547
594
  s_vpi_value v;
@@ -550,6 +597,7 @@ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
550
597
 
551
598
  err = client_get(max_msg_len, msg);
552
599
  if (err) {
600
+ // Don't send to the Origen log since Origen may not be there
553
601
  vpi_printf("ERROR: Failed to receive from Origen!\n");
554
602
  end_simulation();
555
603
  return 1;
@@ -569,211 +617,317 @@ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
569
617
 
570
618
  opcode = strtok(msg, "^");
571
619
 
572
- switch(*opcode) {
573
- // Define pin
574
- // 0^pin_name^pin_index^drive_wave_ix^capture_wave_ix
575
- //
576
- // 0 for the wave indexes means the default, custom waves
577
- // must therefore start from index 1
578
- //
579
- // The pin index must be uniquely assigned to the pin by the caller
580
- // and must be less than MAX_NUMBER_PINS
581
- //
582
- // 0^tdi^12^0^0
583
- case '0' :
584
- arg1 = strtok(NULL, "^");
585
- arg2 = strtok(NULL, "^");
586
- arg3 = strtok(NULL, "^");
587
- arg4 = strtok(NULL, "^");
588
- //DEBUG("Define Pin: %s, %s, %s, %s\n", arg1, arg2, arg3, arg4);
589
- bridge_define_pin(arg1, arg2, arg3, arg4);
590
- break;
591
- // Set Period
592
- // 1^100000
593
- case '1' :
594
- arg1 = strtok(NULL, "^");
595
- bridge_set_period(arg1);
596
- break;
597
- // Drive Pin
598
- // 2^pin_index^data
599
- //
600
- // 2^12^0
601
- // 2^12^1
602
- case '2' :
603
- arg1 = strtok(NULL, "^");
604
- arg2 = strtok(NULL, "^");
605
- //DEBUG("Drive Pin: %s, %s\n", arg1, arg2);
606
- bridge_drive_pin(arg1, arg2);
607
- break;
608
- // Cycle
609
- // 3^number_of_cycles
610
- //
611
- // 3^1
612
- // 3^65535
613
- case '3' :
614
- arg1 = strtok(NULL, "^");
615
- repeat = strtol(arg1, NULL, 10);
616
- if (repeat) {
617
- repeat = repeat - 1;
618
- }
619
- bridge_cycle();
620
- return 0;
621
- // Compare Pin
622
- // 4^pin_index^data
623
- //
624
- // 4^14^0
625
- // 4^14^1
626
- case '4' :
627
- arg1 = strtok(NULL, "^");
628
- arg2 = strtok(NULL, "^");
629
- bridge_compare_pin(arg1, arg2);
630
- break;
631
- // Don't Care Pin
632
- // 5^pin_index
633
- //
634
- // 5^14
635
- case '5' :
636
- arg1 = strtok(NULL, "^");
637
- bridge_dont_care_pin(arg1);
638
- break;
639
- // Define wave
640
- // 6^wave_index^compare^events
641
- //
642
- // 0 for the wave indexes means the default, custom waves
643
- // must therefore start from index 1
644
- //
645
- // 0 for the compare parameter means it is a drive wave, 1 means it is
646
- // for when the pin is in compare mode
647
- //
648
- // Some example events are shown below:
649
- //
650
- // 6^1^0^0_D_25_0_50_D_75_0 // Drive at 0ns, off at 25ns, drive at 50ns, off at 75ns
651
- case '6' :
652
- arg1 = strtok(NULL, "^");
653
- arg2 = strtok(NULL, "^");
654
- arg3 = strtok(NULL, "^");
655
- //DEBUG("Define Wave: %s, %s, %s\n", arg1, arg2, arg3);
656
- bridge_define_wave(arg1, arg2, arg3);
657
- break;
658
- // Sync-up
659
- // 7^
660
- case '7' :
661
- client_put("OK!\n");
662
- break;
663
- // Complete
664
- // 8^
665
- case '8' :
666
- end_simulation();
667
- return 0;
668
- // Peek
669
- // Returns the current value of the given net
670
- //
671
- // 9^origen.debug.errors
672
- case '9' :
673
- arg1 = strtok(NULL, "^");
674
- handle = vpi_handle_by_name(arg1, NULL);
675
- if (handle) {
676
- //v.format = vpiDecStrVal; // Seems important to set this before get
677
- v.format = vpiBinStrVal;
678
- vpi_get_value(handle, &v);
679
- //DEBUG("%s\n", v.value.str);
680
- sprintf(msg, "%s\n", v.value.str);
681
- client_put(msg);
682
- } else {
683
- client_put("FAIL\n");
684
- }
685
- break;
686
- // Set Pattern Name
687
- // a^atd_ramp_25mhz
688
- case 'a' :
689
- handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("debug.pattern"), NULL);
690
- arg1 = strtok(NULL, "^");
691
-
692
- v.format = vpiStringVal;
693
- v.value.str = arg1;
694
- vpi_put_value(handle, &v, NULL, vpiNoDelay);
695
- break;
696
- // Poke
697
- // Sets the given value on the given net, the number should be
698
- // given as a decimal string
699
- //
700
- // b^origen.debug.errors^15
701
- case 'b' :
702
- arg1 = strtok(NULL, "^");
703
- arg2 = strtok(NULL, "^");
704
- handle = vpi_handle_by_name(arg1, NULL);
705
- if (handle) {
706
- v.format = vpiDecStrVal;
620
+ if (!max_errors_exceeded || (max_errors_exceeded && (
621
+ // When max_errors_exceeded, only continue to process the following opcodes.
622
+ // These are the ones required to enable a controlled shutdown driven by the main Origen process
623
+ // and also any that return data to Origen so that the main process does not get blocked:
624
+ // Sync-up End Simulation Peek Flush Log
625
+ *opcode == '7' || *opcode == '8' || *opcode == '9' || *opcode == 'j' || *opcode == 'k' ||
626
+ // Get version Get timescale Read reg trans Get cycle count
627
+ *opcode == 'i' || *opcode == 'l' || *opcode == 'n' || *opcode == 'o'
628
+ ))) {
629
+ switch(*opcode) {
630
+ // Define pin
631
+ // 0^pin_name^pin_index^drive_wave_ix^capture_wave_ix
632
+ //
633
+ // 0 for the wave indexes means the default, custom waves
634
+ // must therefore start from index 1
635
+ //
636
+ // The pin index must be uniquely assigned to the pin by the caller
637
+ // and must be less than MAX_NUMBER_PINS
638
+ //
639
+ // 0^tdi^12^0^0
640
+ case '0' :
641
+ arg1 = strtok(NULL, "^");
642
+ arg2 = strtok(NULL, "^");
643
+ arg3 = strtok(NULL, "^");
644
+ arg4 = strtok(NULL, "^");
645
+ //DEBUG("Define Pin: %s, %s, %s, %s\n", arg1, arg2, arg3, arg4);
646
+ define_pin(arg1, arg2, arg3, arg4);
647
+ break;
648
+ // Set Period
649
+ // 1^100000
650
+ case '1' :
651
+ arg1 = strtok(NULL, "^");
652
+ set_period(arg1);
653
+ break;
654
+ // Drive Pin
655
+ // 2^pin_index^data
656
+ //
657
+ // 2^12^0
658
+ // 2^12^1
659
+ case '2' :
660
+ arg1 = strtok(NULL, "^");
661
+ arg2 = strtok(NULL, "^");
662
+ //DEBUG("Drive Pin: %s, %s\n", arg1, arg2);
663
+ drive_pin(arg1, arg2);
664
+ break;
665
+ // Cycle
666
+ // 3^number_of_cycles
667
+ //
668
+ // 3^1
669
+ // 3^65535
670
+ case '3' :
671
+ arg1 = strtok(NULL, "^");
672
+ repeat = strtol(arg1, NULL, 10);
673
+ if (repeat) {
674
+ repeat = repeat - 1;
675
+ }
676
+ cycle();
677
+ return 0;
678
+ // Compare Pin
679
+ // 4^pin_index^data
680
+ //
681
+ // 4^14^0
682
+ // 4^14^1
683
+ case '4' :
684
+ arg1 = strtok(NULL, "^");
685
+ arg2 = strtok(NULL, "^");
686
+ compare_pin(arg1, arg2);
687
+ break;
688
+ // Don't Care Pin
689
+ // 5^pin_index
690
+ //
691
+ // 5^14
692
+ case '5' :
693
+ arg1 = strtok(NULL, "^");
694
+ dont_care_pin(arg1);
695
+ break;
696
+ // Define wave
697
+ // 6^wave_index^compare^events
698
+ //
699
+ // 0 for the wave indexes means the default, custom waves
700
+ // must therefore start from index 1
701
+ //
702
+ // 0 for the compare parameter means it is a drive wave, 1 means it is
703
+ // for when the pin is in compare mode
704
+ //
705
+ // Some example events are shown below:
706
+ //
707
+ // 6^1^0^0_D_25_0_50_D_75_0 // Drive at 0ns, off at 25ns, drive at 50ns, off at 75ns
708
+ case '6' :
709
+ arg1 = strtok(NULL, "^");
710
+ arg2 = strtok(NULL, "^");
711
+ arg3 = strtok(NULL, "^");
712
+ //DEBUG("Define Wave: %s, %s, %s\n", arg1, arg2, arg3);
713
+ define_wave(arg1, arg2, arg3);
714
+ break;
715
+ // Sync-up
716
+ // 7^
717
+ case '7' :
718
+ client_put("OK!\n");
719
+ break;
720
+ // Complete
721
+ // 8^
722
+ case '8' :
723
+ end_simulation();
724
+ return 0;
725
+ // Peek
726
+ // Returns the current value of the given net
727
+ //
728
+ // 9^origen.debug.errors
729
+ case '9' :
730
+ arg1 = strtok(NULL, "^");
731
+ handle = vpi_handle_by_name(arg1, NULL);
732
+ if (handle) {
733
+ //v.format = vpiDecStrVal; // Seems important to set this before get
734
+ v.format = vpiBinStrVal;
735
+ vpi_get_value(handle, &v);
736
+ //DEBUG("%s\n", v.value.str);
737
+ sprintf(msg, "%s\n", v.value.str);
738
+ client_put(msg);
739
+ } else {
740
+ client_put("FAIL\n");
741
+ }
742
+ break;
743
+ // Set Pattern Name
744
+ // a^atd_ramp_25mhz
745
+ case 'a' :
746
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("debug.pattern"), NULL);
747
+ arg1 = strtok(NULL, "^");
748
+
749
+ v.format = vpiStringVal;
750
+ v.value.str = arg1;
751
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
752
+ break;
753
+ // Poke
754
+ // Sets the given value on the given net, the number should be
755
+ // given as a decimal string
756
+ //
757
+ // b^origen.debug.errors^15
758
+ case 'b' :
759
+ arg1 = strtok(NULL, "^");
760
+ arg2 = strtok(NULL, "^");
761
+ handle = vpi_handle_by_name(arg1, NULL);
762
+ if (handle) {
763
+ v.format = vpiDecStrVal;
764
+ v.value.str = arg2;
765
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
766
+ }
767
+ break;
768
+ // Set Comment
769
+ // c^0^Some comment about the pattern
770
+ case 'c' :
771
+ arg1 = strtok(NULL, "^");
772
+ arg2 = strtok(NULL, "^");
773
+
774
+ strcpy(comment, ORIGEN_SIM_TESTBENCH_CAT("debug.comments"));
775
+ strcat(comment, arg1);
776
+
777
+ handle = vpi_handle_by_name(comment, NULL);
778
+
779
+ v.format = vpiStringVal;
707
780
  v.value.str = arg2;
708
781
  vpi_put_value(handle, &v, NULL, vpiNoDelay);
709
- }
710
- break;
711
- // Set Comment
712
- // c^0^Some comment about the pattern
713
- case 'c' :
714
- arg1 = strtok(NULL, "^");
715
- arg2 = strtok(NULL, "^");
716
-
717
- strcpy(comment, ORIGEN_SIM_TESTBENCH_CAT("debug.comments"));
718
- strcat(comment, arg1);
719
-
720
- handle = vpi_handle_by_name(comment, NULL);
721
-
722
- v.format = vpiStringVal;
723
- v.value.str = arg2;
724
- vpi_put_value(handle, &v, NULL, vpiNoDelay);
725
- break;
726
- // Log all messages
727
- // d^1 Turn logging on
728
- // d^0 Turn logging off
729
- case 'd' :
730
- arg1 = strtok(NULL, "^");
731
- log_messages = atoi(arg1);
732
- break;
733
- // Capture Pin
734
- // e^pin_index
735
- //
736
- // e^14
737
- case 'e' :
738
- arg1 = strtok(NULL, "^");
739
- bridge_capture_pin(arg1);
740
- break;
741
- // Sync enable
742
- case 'f' :
743
- handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("pins.sync"), NULL);
744
- v.format = vpiDecStrVal;
745
- v.value.str = "1";
746
- vpi_put_value(handle, &v, NULL, vpiNoDelay);
747
- break;
748
- // Sync disable
749
- case 'g' :
750
- handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("pins.sync"), NULL);
751
- v.format = vpiDecStrVal;
752
- v.value.str = "0";
753
- vpi_put_value(handle, &v, NULL, vpiNoDelay);
754
- break;
755
- // Stop Capture Pin
756
- // h^pin_index
757
- //
758
- // h^14
759
- case 'h' :
760
- arg1 = strtok(NULL, "^");
761
- bridge_stop_capture_pin(arg1);
762
- break;
763
- // Get version, returns the version of OrigenSim the DUT object was compiled with
764
- // i^
765
- case 'i' :
766
- client_put(ORIGEN_SIM_VERSION"\n");
767
- break;
768
- // Flush
769
- case 'j' :
770
- vpi_flush();
771
- break;
772
- default :
773
- vpi_printf("ERROR: Illegal message received from Origen: %s\n", orig_msg);
774
- runtime_errors += 1;
775
- end_simulation();
776
- return 1;
782
+ break;
783
+ // Log all messages
784
+ // d^1 Turn logging on
785
+ // d^0 Turn logging off
786
+ case 'd' :
787
+ arg1 = strtok(NULL, "^");
788
+ log_messages = atoi(arg1);
789
+ break;
790
+ // Capture Pin
791
+ // e^pin_index
792
+ //
793
+ // e^14
794
+ case 'e' :
795
+ arg1 = strtok(NULL, "^");
796
+ capture_pin(arg1);
797
+ break;
798
+ // Sync enable
799
+ case 'f' :
800
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("pins.sync"), NULL);
801
+ v.format = vpiDecStrVal;
802
+ v.value.str = "1";
803
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
804
+ break;
805
+ // Sync disable
806
+ case 'g' :
807
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("pins.sync"), NULL);
808
+ v.format = vpiDecStrVal;
809
+ v.value.str = "0";
810
+ vpi_put_value(handle, &v, NULL, vpiNoDelay);
811
+ break;
812
+ // Stop Capture Pin
813
+ // h^pin_index
814
+ //
815
+ // h^14
816
+ case 'h' :
817
+ arg1 = strtok(NULL, "^");
818
+ stop_capture_pin(arg1);
819
+ break;
820
+ // Get version, returns the version of OrigenSim the DUT object was compiled with
821
+ // i^
822
+ case 'i' :
823
+ client_put(ORIGEN_SIM_VERSION"\n");
824
+ break;
825
+ // Flush
826
+ case 'j' :
827
+ vpi_flush();
828
+ break;
829
+ // Log message
830
+ // k^2^A message to output to the console/log
831
+ case 'k' :
832
+ arg1 = strtok(NULL, "^");
833
+ arg2 = strtok(NULL, "^");
834
+ type = atoi(arg1);
835
+ origen_log(type, arg2);
836
+ break;
837
+ // Get timescale, returns a number that maps as follows:
838
+ // -15 - fs
839
+ // -14 - 10fs
840
+ // -13 - 100fs
841
+ // -12 - ps
842
+ // -11 - 10ps
843
+ // -10 - 100ps
844
+ // -9 - ns
845
+ // -8 - 10ns
846
+ // -7 - 100ns
847
+ // -6 - us
848
+ // -5 - 10us
849
+ // -4 - 100us
850
+ // -3 - ms
851
+ // -2 - 10ms
852
+ // -1 - 100ms
853
+ // 0 - s
854
+ // 1 - 10s
855
+ // 2 - 100s
856
+ // l^
857
+ case 'l' :
858
+ timescale = vpi_get(vpiTimeUnit, 0);
859
+ sprintf(msg, "%d\n", timescale);
860
+ client_put(msg);
861
+ break;
862
+ // Set max_errors
863
+ // m^10
864
+ case 'm' :
865
+ arg1 = strtok(NULL, "^");
866
+ max_errors = atoi(arg1);
867
+ break;
868
+ // Read reg transaction
869
+ // n^1 - Start transaction
870
+ // n^0 - Stop transaction
871
+ case 'n' :
872
+ arg1 = strtok(NULL, "^");
873
+
874
+ if (*arg1 == '1') {
875
+ transaction_error_count = 0;
876
+ transaction_open = true;
877
+ } else {
878
+ // Send Origen the error data
879
+ sprintf(msg, "%d,%d\n", transaction_error_count, MAX_TRANSACTION_ERRORS);
880
+ client_put(msg);
881
+ for (int i = 0; i < transaction_error_count; i++) {
882
+ Miscompare *m = &miscompares[i];
883
+
884
+ sprintf(msg, "%s,%llu,%d,%d\n", (*m).pin_name, (*m).cycle, (*m).expected, (*m).received);
885
+ client_put(msg);
886
+
887
+ free((*m).pin_name);
888
+ }
889
+ transaction_open = false;
890
+ if (max_errors_exceeded_during_transaction) {
891
+ on_max_errors_exceeded();
892
+ }
893
+ }
894
+ break;
895
+ // Get cycle count
896
+ // o^
897
+ case 'o' :
898
+ sprintf(msg, "%llu\n", cycle_count);
899
+ client_put(msg);
900
+ break;
901
+ // Set cycle count
902
+ // p^100
903
+ case 'p' :
904
+ arg1 = strtok(NULL, "^");
905
+ cycle_count = atoll(arg1);
906
+ break;
907
+ // Match loop
908
+ // q^1 - Start match loop
909
+ // q^0 - Stop match loop
910
+ case 'q' :
911
+ arg1 = strtok(NULL, "^");
912
+
913
+ if (*arg1 == '1') {
914
+ match_loop_error_count = 0;
915
+ match_loop_open = true;
916
+ } else {
917
+ match_loop_open = false;
918
+ }
919
+ break;
920
+ default :
921
+ origen_log(LOG_ERROR, "Illegal message received from Origen: %s", orig_msg);
922
+ runtime_errors += 1;
923
+ end_simulation();
924
+ return 1;
925
+ }
926
+ } else {
927
+ // Simulation has been aborted but not told to end yet by Origen
928
+ repeat = 0;
929
+ set_period("1");
930
+ cycle();
777
931
  }
778
932
  free(orig_msg);
779
933
  }
@@ -790,29 +944,31 @@ static void end_simulation() {
790
944
  v.value.str = "1";
791
945
  vpi_put_value(handle, &v, NULL, vpiNoDelay);
792
946
  // Corner case during testing, the timeset may not have been set yet
793
- bridge_set_period("1000");
947
+ set_period("1");
794
948
  // Do a cycle so that the simulation sees the edge on origen.finish
795
- bridge_cycle();
949
+ cycle();
796
950
  }
797
951
 
798
952
 
799
- PLI_INT32 bridge_cycle_cb(p_cb_data data) {
953
+ PLI_INT32 cycle_cb(p_cb_data data) {
800
954
  UNUSED(data);
801
955
  repeat = repeat - 1;
802
- bridge_cycle();
956
+ cycle();
803
957
  return 0;
804
958
  }
805
959
 
806
960
 
807
961
  /// Registers a callback after a cycle period, the main server loop should unblock
808
962
  /// after calling this to allow the simulation to proceed for a cycle
809
- static void bridge_cycle() {
963
+ static void cycle() {
810
964
  s_cb_data call;
811
965
  s_vpi_time time;
812
966
 
813
967
  time.type = vpiSimTime;
814
- time.high = (uint32_t)(period_in_ps >> 32);
815
- time.low = (uint32_t)(period_in_ps);
968
+ time.high = (uint32_t)(period_in_simtime_units >> 32);
969
+ time.low = (uint32_t)(period_in_simtime_units);
970
+
971
+ cycle_count++;
816
972
 
817
973
  call.reason = cbAfterDelay;
818
974
  call.obj = 0;
@@ -822,12 +978,105 @@ static void bridge_cycle() {
822
978
 
823
979
  //DEBUG("REPEAT: %d\n", repeat);
824
980
  if (repeat) {
825
- call.cb_rtn = bridge_cycle_cb;
981
+ call.cb_rtn = cycle_cb;
826
982
  } else {
827
983
  call.cb_rtn = bridge_wait_for_msg;
828
984
  }
829
985
 
830
986
  vpi_free_object(vpi_register_cb(&call));
831
987
 
832
- bridge_register_wave_events();
988
+ register_wave_events();
989
+ }
990
+
991
+ static void on_max_errors_exceeded() {
992
+ // This will cause the simulation to stop processing messages from Origen
993
+ max_errors_exceeded = true;
994
+ // And this let's the Origen process know that we have stopped processing
995
+ origen_log(LOG_ERROR, "!MAX_ERROR_ABORT!");
996
+ }
997
+
998
+ /// Called every time a miscompare event occurs, 3 args will be passed in:
999
+ /// the pin name, expected data, actual data
1000
+ PLI_INT32 bridge_on_miscompare(PLI_BYTE8 * user_dat) {
1001
+ char *pin_name;
1002
+ int expected;
1003
+ int received;
1004
+ s_vpi_value val;
1005
+ vpiHandle handle;
1006
+
1007
+ if (match_loop_open) {
1008
+ match_loop_error_count++;
1009
+
1010
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("debug.match_errors"), NULL);
1011
+ val.format = vpiIntVal;
1012
+ val.value.integer = match_loop_error_count;
1013
+ vpi_put_value(handle, &val, NULL, vpiNoDelay);
1014
+
1015
+ } else {
1016
+ vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
1017
+ vpiHandle argv = vpi_iterate(vpiArgument, callh);
1018
+ vpiHandle arg;
1019
+
1020
+ arg = vpi_scan(argv);
1021
+ val.format = vpiStringVal;
1022
+ vpi_get_value(arg, &val);
1023
+ pin_name = val.value.str;
1024
+
1025
+ arg = vpi_scan(argv);
1026
+ val.format = vpiIntVal;
1027
+ vpi_get_value(arg, &val);
1028
+ expected = val.value.integer;
1029
+
1030
+ arg = vpi_scan(argv);
1031
+ val.format = vpiIntVal;
1032
+ vpi_get_value(arg, &val);
1033
+ received = val.value.integer;
1034
+
1035
+ vpi_free_object(argv);
1036
+
1037
+ origen_log(LOG_ERROR, "Miscompare on pin %s, expected %d received %d", pin_name, expected, received);
1038
+
1039
+ error_count++;
1040
+
1041
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("debug.errors"), NULL);
1042
+ val.format = vpiIntVal;
1043
+ val.value.integer = error_count;
1044
+ vpi_put_value(handle, &val, NULL, vpiNoDelay);
1045
+
1046
+ if (error_count > max_errors) {
1047
+ // If a transaction is currently open hold off aborting until after that has completed
1048
+ // to enable a proper error message to be generated for it
1049
+ if (transaction_open) {
1050
+ max_errors_exceeded_during_transaction = true;
1051
+ } else {
1052
+ on_max_errors_exceeded();
1053
+ }
1054
+ }
1055
+
1056
+ // Store all errors during a transaction
1057
+ if (transaction_open) {
1058
+ if (transaction_error_count < MAX_TRANSACTION_ERRORS) {
1059
+ Miscompare *miscompare = &miscompares[transaction_error_count];
1060
+
1061
+ (*miscompare).pin_name = malloc(strlen(pin_name) + 1);
1062
+ strcpy((*miscompare).pin_name, pin_name);
1063
+ (*miscompare).cycle = cycle_count;
1064
+ (*miscompare).expected = expected;
1065
+ (*miscompare).received = received;
1066
+ }
1067
+ transaction_error_count++;
1068
+ }
1069
+ }
1070
+ return 0;
1071
+ }
1072
+
1073
+ /// Defines which functions are callable from Verilog as system tasks
1074
+ void bridge_register_system_tasks() {
1075
+ s_vpi_systf_data tf_data;
1076
+
1077
+ tf_data.type = vpiSysTask;
1078
+ tf_data.tfname = "$bridge_on_miscompare";
1079
+ tf_data.calltf = bridge_on_miscompare;
1080
+ tf_data.compiletf = 0;
1081
+ vpi_register_systf(&tf_data);
833
1082
  }