simulavr  1.1.0
vpi.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002 Stephen Williams (steve@icarus.com)
3  * Copyright (c) 2007 Onno Kortmann <onno@gmx.net>
4  *
5  * This source code is free software; you can redistribute it
6  * and/or modify it in source code form under the terms of the GNU
7  * General Public License as published by the Free Software
8  * Foundation; either version 2 of the License, or (at your option)
9  * any later version.
10  *
11  * This program 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 along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * $Id$
21  */
22 
23 /* This has been adapted from the hello_vpi.c example in the Icarus Verilog Source
24  Distribution. */
25 
26 #include "config.h"
27 #if HAVE_IVERILOG_VPI_USER_H
28 #include <iverilog/vpi_user.h>
29 #else
30 #include <vpi_user.h>
31 #endif
32 
33 #include "avrdevice.h"
34 #include "avrfactory.h"
35 #include "rwmem.h"
36 #include "pin.h"
37 #include "avrerror.h"
38 #include "cmd/dumpargs.h"
39 #include "systemclock.h"
40 
41 static std::vector<AvrDevice*> devices;
42 
43 static bool checkHandle(int h) {
44  if (h>=devices.size()) {
45  vpi_printf("There has never been an AVR device with the handle %d.", h);
46  vpi_control(vpiFinish, 1);
47  return false;
48  } else {
49  if (!devices[h]) {
50  vpi_printf("The AVR with handle %d has already been destroyed.", h);
51  vpi_control(vpiFinish, 1);
52  return false;
53  }
54  }
55  return true;
56 }
57 
58 #define VPI_UNPACKS(name) \
59  { \
60  vpiHandle name = vpi_scan(argv); \
61  if (! name) { \
62  vpi_printf("%s: " #name " parameter missing.\n", xx);\
63  vpi_free_object(argv); \
64  return 0; \
65  } \
66  value.format = vpiStringVal; \
67  vpi_get_value(name, &value); \
68  } \
69  std::string name = value.value.str;
70 
71 #define VPI_UNPACKI(name) \
72  { \
73  vpiHandle name = vpi_scan(argv); \
74  if (! name) { \
75  vpi_printf("%s: " #name " parameter missing.\n", xx);\
76  vpi_free_object(argv); \
77  return 0; \
78  } \
79  value.format = vpiIntVal; \
80  vpi_get_value(name, &value); \
81  } \
82  int name = value.value.integer;
83 
84 #define VPI_UNPACKT(name) \
85  { \
86  vpiHandle name = vpi_scan(argv); \
87  if (! name) { \
88  vpi_printf("%s: " #name " parameter missing.\n", xx);\
89  vpi_free_object(argv); \
90  return 0; \
91  } \
92  value.format = vpiTimeVal; \
93  vpi_get_value(name, &value); \
94  } \
95  t_vpi_time *name = value.value.time;
96 
97 #define VPI_RETURN_INT(val) \
98  value.format = vpiIntVal; \
99  value.value.integer = (val); \
100  vpi_put_value(ch, &value, 0, vpiNoDelay); \
101  return 0;
102 
103 #define AVR_HCHECK() \
104  if (!checkHandle(handle)) { \
105  vpi_printf("%s: Invalid handle parameter.\n", xx); \
106  return 0; \
107  }
108 
109 #define VPI_BEGIN() \
110  s_vpi_value value; \
111  vpiHandle ch = vpi_handle(vpiSysTfCall, 0); \
112  vpiHandle argv = vpi_iterate(vpiArgument, ch);
113 
114 #define VPI_END() \
115  vpi_free_object(argv);
116 
117 #define VPI_REGISTER_TASK(name) \
118  { \
119  s_vpi_systf_data tf_data; \
120  tf_data.type = vpiSysTask; \
121  tf_data.tfname = "$" #name; \
122  tf_data.calltf = name ## _tf; \
123  tf_data.compiletf = 0; \
124  tf_data.sizetf = 0; \
125  tf_data.user_data = (PLI_BYTE8 *)"$" #name; \
126  vpi_register_systf(&tf_data); \
127  }
128 
129 #define VPI_REGISTER_FUNC(name) \
130  { \
131  s_vpi_systf_data tf_data; \
132  tf_data.type = vpiSysFunc; \
133  tf_data.tfname = "$" #name; \
134  tf_data.calltf = name ## _tf; \
135  tf_data.compiletf = 0; \
136  tf_data.sizetf = 0; \
137  tf_data.user_data = (PLI_BYTE8 *)"$" #name; \
138  vpi_register_systf(&tf_data); \
139  }
140 
153 static PLI_INT32 avr_create_tf(char *xx) {
154  VPI_BEGIN();
155  VPI_UNPACKS(device);
156  VPI_UNPACKS(progname);
157  VPI_END();
158 
159  AvrDevice* dev=AvrFactory::instance().makeDevice(device.c_str());
160  devices.push_back(dev);
161 
162  dev->Load(progname.c_str());
163 
164  VPI_RETURN_INT(devices.size()-1);
165 }
166 
173 static PLI_INT32 avr_reset_tf(char *xx) {
174  VPI_BEGIN();
175  VPI_UNPACKI(handle);
176  VPI_END();
177 
178  AVR_HCHECK();
179  devices[handle]->Reset();
180  return 0;
181 }
182 
189 static PLI_INT32 avr_destroy_tf(char *xx) {
190  VPI_BEGIN();
191  VPI_UNPACKI(handle);
192  VPI_END();
193 
194  AVR_HCHECK();
195 
196  /* We may leak a bity of memory for the pointer in the vector,
197  but... what the hell! */
198  delete devices[handle];
199  devices[handle]=0;
200  return 0;
201 }
202 
209 static PLI_INT32 avr_tick_tf(char *xx) {
210  VPI_BEGIN();
211  VPI_UNPACKI(handle);
212  VPI_END();
213  AVR_HCHECK();
214 
215  bool no_hw=false;
216  devices[handle]->Step(no_hw);
217  return 0;
218 }
219 
224 static PLI_INT32 avr_set_time_tf(char *xx) {
225  VPI_BEGIN();
226  VPI_UNPACKT(time);
227  VPI_END();
228 
229  // For some weird reason (bug?) the low part is the high longword, really...
230  uint64_t tfull=(time->low)<<32+((uint64_t) time->high);
232 
233  return 0;
234 }
235 
241 static PLI_INT32 avr_get_pin_tf(char *xx) {
242  VPI_BEGIN();
243  VPI_UNPACKI(handle);
244  VPI_UNPACKS(name);
245  VPI_END();
246 
247  AVR_HCHECK();
248 
249  Pin *pin=devices[handle]->GetPin(name.c_str());
250  int ret(pin->outState);
251 
252  VPI_RETURN_INT(ret);
253 }
254 
260 static PLI_INT32 avr_set_pin_tf(char *xx) {
261  VPI_BEGIN();
262  VPI_UNPACKI(handle);
263  VPI_UNPACKS(name);
264  VPI_UNPACKI(val);
265  VPI_END();
266 
267  AVR_HCHECK();
268 
269  Pin *pin=devices[handle]->GetPin(name.c_str());
270 
271  /* FIXME: Simply exports AVR pin states to verilog. This
272  may be considered a breach of abstractions.
273  */
274  pin->SetInState(Pin::T_Pinstate(val));
275  return 0;
276 }
277 
284 static PLI_INT32 avr_get_pc_tf(char *xx) {
285  VPI_BEGIN();
286  VPI_UNPACKI(handle);
287  VPI_END();
288 
289  AVR_HCHECK();
290 
291  VPI_RETURN_INT(devices[handle]->cPC);
292 }
293 
303 static PLI_INT32 avr_get_rw_tf(char *xx) {
304  VPI_BEGIN();
305  VPI_UNPACKI(handle);
306  VPI_UNPACKI(address);
307  VPI_END();
308 
309  AVR_HCHECK();
310 
311  VPI_RETURN_INT(devices[handle]->GetRWMem(address));
312 }
313 
323 static PLI_INT32 avr_set_rw_tf(char *xx) {
324  VPI_BEGIN();
325  VPI_UNPACKI(handle);
326  VPI_UNPACKI(address);
327  VPI_UNPACKI(val);
328  VPI_END();
329 
330  AVR_HCHECK();
331 
332  devices[handle]->SetRWMem(address, val);
333  return 0;
334 }
335 
349 static PLI_INT32 avr_trace_tf(char *xx) {
350  VPI_BEGIN();
351  VPI_UNPACKS(tracename);
352  VPI_END();
353 
354  if (tracename.length()) {
355  sysConHandler.SetTraceFile(tracename.c_str(), 1000000);
356  for (size_t i=0; i < devices.size(); i++)
357  devices[i]->trace_on=1;
358  } else {
360  for (size_t i=0; i < devices.size(); i++)
361  devices[i]->trace_on=0;
362  }
363  return 0;
364 }
365 
369 static PLI_INT32 avr_dump_arg_tf(char *xx) {
370  VPI_BEGIN();
371  VPI_UNPACKI(handle);
372  VPI_UNPACKS(dumparg);
373  VPI_END();
374  AVR_HCHECK();
375  std::vector<std::string> dargs;
376  dargs.push_back(dumparg);
377  SetDumpTraceArgs(dargs, devices[handle]);
378  return 0;
379 }
380 
383 static PLI_INT32 avr_dump_start_tf(char *xx) {
385  return 0;
386 }
387 
389 static PLI_INT32 avr_dump_stop_tf(char *xx) {
391  return 0;
392 }
393 
394 static void register_tasks() {
395  VPI_REGISTER_FUNC(avr_create);
396  VPI_REGISTER_TASK(avr_reset);
397  VPI_REGISTER_TASK(avr_destroy);
398  VPI_REGISTER_TASK(avr_tick);
399  VPI_REGISTER_TASK(avr_set_time);
400  VPI_REGISTER_FUNC(avr_get_pin);
401  VPI_REGISTER_TASK(avr_set_pin);
402  VPI_REGISTER_FUNC(avr_get_pc);
403  VPI_REGISTER_FUNC(avr_get_rw);
404  VPI_REGISTER_TASK(avr_set_rw);
405  VPI_REGISTER_TASK(avr_trace);
406  VPI_REGISTER_TASK(avr_dump_arg);
407  VPI_REGISTER_TASK(avr_dump_start);
408  VPI_REGISTER_TASK(avr_dump_stop);
409 }
410 
411 /* This is a table of register functions. This table is the external symbol
412  that the simulator looks for when loading this .vpi module. */
413 void (*vlog_startup_routines[])() = {
415  0
416 };
void start()
Definition: traceval.cpp:680
static std::vector< AvrDevice * > devices
Definition: vpi.cpp:41
Basic AVR device, contains the core functionality.
Definition: avrdevice.h:66
static PLI_INT32 avr_tick_tf(char *xx)
Definition: vpi.cpp:209
static bool checkHandle(int h)
Definition: vpi.cpp:43
#define VPI_UNPACKI(name)
Definition: vpi.cpp:71
static PLI_INT32 avr_get_pin_tf(char *xx)
Definition: vpi.cpp:241
SystemConsoleHandler sysConHandler
The SystemConsoleHandler instance for common usage.
Definition: avrerror.cpp:234
Pin class, handles input and output to external parts.
Definition: pin.h:98
void(* vlog_startup_routines[])()
Definition: vpi.cpp:413
#define VPI_RETURN_INT(val)
Definition: vpi.cpp:97
#define VPI_UNPACKT(name)
Definition: vpi.cpp:84
static PLI_INT32 avr_get_rw_tf(char *xx)
Definition: vpi.cpp:303
static PLI_INT32 avr_set_rw_tf(char *xx)
Definition: vpi.cpp:323
void SetTraceFile(const char *name, unsigned int maxlines=0)
Sets the trace to file stream and enables tracing global.
Definition: avrerror.cpp:83
static PLI_INT32 avr_get_pc_tf(char *xx)
Definition: vpi.cpp:284
#define VPI_REGISTER_FUNC(name)
Definition: vpi.cpp:129
T_Pinstate
Possible PIN states.
Definition: pin.h:115
static PLI_INT32 avr_trace_tf(char *xx)
Definition: vpi.cpp:349
static AvrFactory & instance()
Singleton class access.
Definition: avrfactory.cpp:73
void stopApplication(void)
Stop processing on all dumpers and removes it from dumpers list.
Definition: traceval.cpp:701
#define VPI_REGISTER_TASK(name)
Definition: vpi.cpp:117
void StopTrace(void)
Stops tracing global, close file, if set, redirect trace to nullStream.
Definition: avrerror.cpp:108
static SystemClock & Instance()
Returns the central SystemClock instance for the application.
T_Pinstate outState
discrete value of output stage
Definition: pin.h:126
AvrDevice * makeDevice(const char *config)
Definition: avrfactory.cpp:51
static PLI_INT32 avr_dump_stop_tf(char *xx)
Definition: vpi.cpp:389
#define VPI_END()
Definition: vpi.cpp:114
static PLI_INT32 avr_set_pin_tf(char *xx)
Definition: vpi.cpp:260
static void register_tasks()
Definition: vpi.cpp:394
#define VPI_BEGIN()
Definition: vpi.cpp:109
void SetCurrentTime(SystemClockOffset of)
Set the simulation time to a dedicated value.
Definition: systemclock.h:98
static PLI_INT32 avr_reset_tf(char *xx)
Definition: vpi.cpp:173
#define AVR_HCHECK()
Definition: vpi.cpp:103
virtual void SetInState(const Pin &p)
handles the input value from net
Definition: pin.cpp:64
void Load(const char *n)
Load flash, eeprom, signature, fuses from elf file, wrapper for LoadBFD or LoadSimpleELF.
Definition: avrdevice.cpp:63
static PLI_INT32 avr_destroy_tf(char *xx)
Definition: vpi.cpp:189
#define VPI_UNPACKS(name)
Definition: vpi.cpp:58
static DumpManager * Instance(void)
Singleton class access.
Definition: traceval.cpp:567
static PLI_INT32 avr_dump_start_tf(char *xx)
Definition: vpi.cpp:383
static PLI_INT32 avr_set_time_tf(char *xx)
Definition: vpi.cpp:224
void SetDumpTraceArgs(const std::vector< std::string > &traceopts, AvrDevice *dev)
Parse given trace options and open Dumper.
static PLI_INT32 avr_dump_arg_tf(char *xx)
Definition: vpi.cpp:369
static PLI_INT32 avr_create_tf(char *xx)
Definition: vpi.cpp:153