origen_sim 0.15.0 → 0.16.0

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
  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
  }