1 /*
2 Copyright (C) 1999 T. Scott Dattalo
3
4 This file is part of gpsim.
5
6 gpsim is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 gpsim is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with gpsim; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include <iostream>
23 #include <iomanip>
24 #include <string>
25 #include <vector>
26
27 #include "command.h"
28 #include "cmd_stimulus.h"
29 #include "../src/pic-processor.h"
30 #include "../src/stimuli.h"
31 #include "../src/symbol.h"
32
33
34 static ValueStimulus *last_stimulus=0;
35 cmd_stimulus c_stimulus;
36
37 #define ASYNCHRONOUS_STIMULUS 1
38 #define SYNCHRONOUS_STIMULUS 2
39
40 #define STIM_NOTHING 0
41 #define STIM_PERIOD (1 << 0)
42 #define STIM_PHASE (1 << 1)
43 #define STIM_HIGH_TIME (1 << 2)
44 #define STIM_INITIAL_STATE (1 << 3)
45 #define STIM_START_CYCLE (1 << 4)
46 #define STIM_DATA (1 << 5)
47
48 #define STIM_ASY (1 << 7)
49 #define STIM_SQW (1 << 8)
50 #define STIM_NAME (1 << 9)
51 #define STIM_TRI (1 << 10)
52 #define STIM_ATTRIBUTE (1 << 11)
53 #define STIM_ANALOG (1 << 12)
54 #define STIM_DIGITAL (1 << 13)
55 #define STIM_DUMP (1 << 14)
56
57 const unsigned int
58 SQW_OPTIONS = STIM_SQW | STIM_PERIOD | STIM_PHASE | STIM_HIGH_TIME | STIM_START_CYCLE;
59 const unsigned int
60 ASY_OPTIONS = STIM_ASY | STIM_PERIOD | STIM_PHASE | STIM_HIGH_TIME | STIM_START_CYCLE | STIM_DATA;
61 const unsigned int
62 TRI_OPTIONS = STIM_TRI | STIM_PERIOD | STIM_PHASE | STIM_HIGH_TIME | STIM_START_CYCLE;
63 const unsigned int
64 ATTR_OPTIONS = STIM_ATTRIBUTE | STIM_PERIOD | STIM_PHASE | STIM_HIGH_TIME | STIM_START_CYCLE | STIM_DATA;
65
66 static cmd_options cmd_stimulus_options[] =
67 {
68 {"asy", STIM_ASY, OPT_TT_SUBTYPE},
69 {"asynchronous_stimulus", STIM_ASY, OPT_TT_SUBTYPE},
70 {"attr", STIM_ATTRIBUTE, OPT_TT_SUBTYPE},
71 {"attribute_stimulus", STIM_ATTRIBUTE, OPT_TT_SUBTYPE},
72 {"period", STIM_PERIOD, OPT_TT_NUMERIC},
73 {"phase", STIM_PHASE, OPT_TT_NUMERIC},
74 {"high_time", STIM_HIGH_TIME, OPT_TT_NUMERIC},
75 {"initial_state", STIM_INITIAL_STATE, OPT_TT_NUMERIC},
76 {"start_cycle", STIM_START_CYCLE, OPT_TT_NUMERIC},
77 {"start", STIM_START_CYCLE, OPT_TT_NUMERIC},
78 {"name", STIM_NAME, OPT_TT_STRING},
79 {"digital", STIM_DIGITAL, OPT_TT_BITFLAG},
80 {"analog", STIM_ANALOG, OPT_TT_BITFLAG},
81 {"d", STIM_DUMP, OPT_TT_BITFLAG},
82 {"dump", STIM_DUMP, OPT_TT_BITFLAG},
83 {"sqw", STIM_SQW, OPT_TT_SUBTYPE},
84 {"square_wave", STIM_SQW, OPT_TT_SUBTYPE},
85 {"tri", STIM_TRI, OPT_TT_SUBTYPE},
86 {"triangle_wave", STIM_TRI, OPT_TT_SUBTYPE},
87
88 { 0,0,0}
89 };
90
91
cmd_stimulus()92 cmd_stimulus::cmd_stimulus()
93 : command("stimulus","stim")
94 {
95
96 brief_doc = string("Create a stimulus");
97
98 long_doc = string ("\nstimulus [[type] options]\n"
99 "\tstimulus will create a signal that can be tied to a node or an\n"
100 "\attribute. Note that in most cases it is easier to create a\n"
101 "\tstimulus file then to type this by hand.\n"
102 "\n"
103 "\t Supported stimuli:\n"
104 "\n"
105 //"\tsquare_wave | sqw [period p] [high_time h] [phase ph] [initial_state i]\n"
106 //"\t port port_name bit_pos end\n"
107 //"\t\t creates a square wave with a period of \"p\" cpu cycles.\n"
108 //"\t\t If the high time is specified then that's the number of cycles\n"
109 //"\t\t the square wave will be high.\n"
110 //"\t\t The phase is with respect to the cpu's cycle counter.\n"
111 //"\t\t The \"port_name\" and \"bit_pos\" describe where the stimulus\n"
112 //"\t\t will be attached.\n"
113 "\tasynchronous_stimulus | asy [period p] [phase ph] [initial_state i]\n"
114 "\t { c0,e0 [,c1, e1, c2, e2, ... ,cn,en] } [name stim_name] end\n"
115 "\t\t creates an asynchronous square wave with a period of \"p\" cpu\n"
116 "\t\t cycles. The phase is with respect to the cpu's cycle counter.\n"
117 "\t\t The data is specified as a pair of expressions. The first expression\n"
118 "\t\t is for the cycle time and the second is the data. "
119 "\n"
120 "\texamples:\n"
121 "\n"
122 //"\t stimulus sqw period 200 high_time 20 phase 60 port portb 0 end\n"
123 //"\t create a square wave stimulus that repeats every 200 cpu cycles,\n"
124 //"\t is high for 20 cpu cycles (and low for 200-20=180 cycles). The\n"
125 //"\t first rising edge will occur at cycle\n"
126 //"\t 60, the second at 260, . . . Bit 0 of portb will receive the stimulus.\n"
127
128 "\t # define a stimulus to generate two pulses every 1000 cycles\n"
129 "\t \n"
130 "\t stimulus asynchronous_stimulus \n"
131 "\t \n"
132 "\t # The initial state AND the state the stimulus is when\n"
133 "\t # it rolls over\n"
134 "\t \n"
135 "\t initial_state 0\n"
136 "\t start_cycle 0\n"
137 "\t \n"
138 "\t # the asynchronous stimulus will roll over in 'period'\n"
139 "\t # cycles. Delete this line if you don't want a roll over.\n"
140 "\t \n"
141 "\t period 1000\n"
142 "\t \n"
143 "\t { 100, 1,\n"
144 "\t 200, 0,\n"
145 "\t 300, 1,\n"
146 "\t 400, 0\n"
147 "\t }\n"
148 "\t \n"
149 "\t # Give the stimulus a name:\n"
150 "\t \n"
151 "\t name two_pulse_repeat\n"
152 "\t \n"
153 "\t end\n"
154 "\n");
155
156 op = cmd_stimulus_options;
157
158 options_entered = 0;
159
160 }
161
162 static string table_name;
163
dumpStimulus(const SymbolEntry_t & sym)164 void dumpStimulus(const SymbolEntry_t &sym)
165 {
166 stimulus *ps = dynamic_cast<stimulus *>(sym.second);
167
168 if (ps) {
169 cout << table_name << ".";
170 cout << ps->name();
171 ps->show();
172 cout << endl;
173 }
174 }
175
dumpStimuli(const SymbolTableEntry_t & st)176 void dumpStimuli(const SymbolTableEntry_t &st)
177 {
178 cout << " Symbol Table: " << st.first << endl;
179 table_name = st.first;
180 (st.second)->ForEachSymbolTable(dumpStimulus);
181 }
182
stimulus()183 void cmd_stimulus::stimulus()
184 {
185 cout << "\nSymbol table\n";
186 globalSymbolTable().ForEachModule(dumpStimuli);
187 }
188
189 //------------------------------------------------------------------
190 // stimulus(int bit_flag)
191 //
192 // For the bit_flags of SQW, ASY, TRI:
193 // A new stimulus is dynamically created and a pointer to it is
194 // is assigned to 'last_stimulus'. The last_stimulus also acts like
195 // a flag. If it is non-null then a stimulus is in the process of
196 // being created. When the stimulus 'end' option is specified at the
197 // cli, then 'last_stimulus' is set to NULL. Note the memory for
198 // used by the last stimulus is created here, but destroyed by the
199 // stimulus code in ../src/stimuli.cc .
200 //
stimulus(int bit_flag)201 void cmd_stimulus::stimulus(int bit_flag)
202 {
203
204 switch(bit_flag)
205 {
206 case STIM_SQW:
207 if(verbose)
208 cout << "creating sqw stimulus\n";
209 if(!last_stimulus) {
210 //create_stimulus(NEW_SQW,stim_name);
211 valid_options = SQW_OPTIONS;
212 options_entered = STIM_SQW;
213 //last_stimulus = new square_wave;
214 } else
215 cout << "warning: ignoring sqw stim creation";
216 break;
217
218 case STIM_ASY:
219 if(verbose)
220 cout << "creating asy stimulus\n";
221
222 if(!last_stimulus) {
223 //create_stimulus(NEW_ASY,stim_name);
224 last_stimulus = new ValueStimulus;
225 valid_options = ASY_OPTIONS;
226 options_entered = STIM_ASY;
227 }else
228 cout << "warning: ignoring asy stim creation";
229 break;
230
231 case STIM_ATTRIBUTE:
232 if(verbose)
233 cout << "creating asy stimulus\n";
234
235 if(!last_stimulus) {
236 last_stimulus = new AttributeStimulus;
237 valid_options = ATTR_OPTIONS;
238 options_entered = STIM_ATTRIBUTE;
239 }else
240 cout << "warning: ignoring asy stim creation";
241 break;
242
243 case STIM_TRI:
244 if(verbose)
245 cout << "creating tri stimulus\n";
246
247 if(!last_stimulus) {
248 //create_stimulus(NEW_TRI,stim_name);
249 //last_stimulus = new triangle_wave;
250 valid_options = TRI_OPTIONS;
251 options_entered = STIM_TRI;
252 } else
253 cout << "warning: ignoring tri stim creation";
254 break;
255
256 case STIM_DUMP:
257 stimulus(); // Display the list of stimuli.
258 return;
259
260 case STIM_DIGITAL:
261 if(last_stimulus)
262 last_stimulus->set_digital();
263 return;
264
265 case STIM_ANALOG:
266 if(last_stimulus)
267 last_stimulus->set_analog();
268 return;
269
270 default:
271 cout << " Invalid stimulus option\n";
272 return;
273 }
274
275 }
276
277
stimulus(cmd_options_expr * coe)278 void cmd_stimulus::stimulus(cmd_options_expr *coe)
279 {
280 /*
281 double dvalue = 0.0;
282 if(coe->expr)
283 dvalue = evaluate(coe->expr);
284
285 int value = (int) dvalue;
286 */
287
288 if (!coe || !coe->expr)
289 return;
290
291 Value *value = toValue(coe->expr);
292
293 switch(coe->co->value)
294 {
295 case STIM_PHASE:
296 if(verbose)
297 cout << "stimulus command got the phase " << value << '\n';
298
299 if(last_stimulus)
300 last_stimulus->put_phase(value);
301
302 break;
303
304 case STIM_PERIOD:
305 if(verbose)
306 cout << "stimulus command got the period " << value << '\n';
307
308 if(last_stimulus)
309 last_stimulus->put_period(value);
310
311 break;
312
313 case STIM_HIGH_TIME:
314 if(verbose)
315 cout << "stimulus command got the high_time " << value << '\n';
316
317 if(last_stimulus)
318 last_stimulus->put_duty(value);
319
320 break;
321
322 case STIM_INITIAL_STATE:
323 if(verbose)
324 cout << "stimulus command got the initial_state " << value << '\n';
325
326 if(last_stimulus)
327 last_stimulus->put_initial_state(value);
328
329 break;
330
331 case STIM_START_CYCLE:
332 if(verbose)
333 cout << "stimulus command got the start_cycle " << value << '\n';
334
335 if(last_stimulus)
336 last_stimulus->put_start_cycle(value);
337
338 break;
339
340 default:
341 cout << " Invalid stimulus option\n";
342 return;
343 }
344
345 options_entered |= coe->co->value;
346 delete coe->expr;
347 delete value;
348
349 }
350
351
stimulus(cmd_options_str * cos)352 void cmd_stimulus::stimulus(cmd_options_str *cos)
353 {
354
355 if(!last_stimulus) {
356 cout << "warning: Ignoring stimulus (string) option because there's no stimulus defined.\n";
357 return;
358 }
359
360
361 switch(cos->co->value)
362 {
363 case STIM_NAME:
364 if(verbose)
365 cout << "stimulus command got the name " << cos->str << '\n';
366
367 last_stimulus->new_name(cos->str);
368
369 break;
370 }
371
372 options_entered |= cos->co->value;
373 }
374
stimulus(ExprList_t * eList)375 void cmd_stimulus::stimulus(ExprList_t *eList)
376 {
377 ExprList_itor ei;
378
379 bool bHaveSample=false;
380 ValueStimulusData sample;
381 sample.time = 0;
382 sample.v = 0;
383
384 if(last_stimulus) {
385 for(ei = eList->begin(); ei != eList->end(); ++ei) {
386
387
388
389 try {
390
391 Value *v = (*ei)->evaluate();
392
393 if(!bHaveSample) {
394 v->get(sample.time);
395 delete v;
396 bHaveSample = true;
397 } else {
398 sample.v = v;
399 last_stimulus->put_data(sample);
400 bHaveSample = false;
401 have_data = 1;
402 }
403
404 }
405
406 catch (Error &err) {
407 std::cout << "ERROR:" << err.what() << '\n';
408 }
409
410 }
411
412 }
413
414 eList->clear();
415 delete eList;
416 }
417
418 //-----------------
419 // end()
420 // All of the stimulus' options have been entered. Now it's time
421 // to create the stimulus.
422
end()423 void cmd_stimulus::end()
424 {
425 if(!last_stimulus) {
426 cout << "warning: Ignoring stimulus (string) option because there's no stimulus defined.";
427 return;
428 }
429
430 switch( options_entered & (STIM_SQW | STIM_TRI | STIM_ASY | STIM_ATTRIBUTE))
431 {
432 case STIM_SQW:
433 if(verbose)
434 cout << "created sqw stimulus\n";
435 break;
436
437 case STIM_ASY:
438 if(verbose)
439 cout << "created asy stimulus\n";
440 last_stimulus->start();
441 break;
442
443 case STIM_ATTRIBUTE:
444 if(verbose)
445 cout << "created attribute stimulus\n";
446 last_stimulus->start();
447 break;
448
449 case STIM_TRI:
450 if(verbose)
451 cout << "creating tri stimulus\n";
452 break;
453
454 }
455
456 last_stimulus = 0;
457 }
458