sv_api/lib.rs
1/*
2 * File: lib.rs
3 * Brief: TODO
4 *
5 * Copyright (C) 2023 John Jekel
6 * See the LICENSE file at the root of the project for licensing info.
7 *
8 * TODO longer description
9 *
10*/
11
12/*!
13 * TODO rustdoc for this file here
14*/
15
16/* ------------------------------------------------------------------------------------------------
17 * Submodules
18 * --------------------------------------------------------------------------------------------- */
19
20pub mod callbacks;
21pub mod info;
22pub mod result;
23pub mod startup;
24pub mod print;
25
26/* ------------------------------------------------------------------------------------------------
27 * Uses
28 * --------------------------------------------------------------------------------------------- */
29
30//TODO (includes "use ..." and "extern crate ...")
31
32/* ------------------------------------------------------------------------------------------------
33 * Macros
34 * --------------------------------------------------------------------------------------------- */
35
36//TODO
37
38/* ------------------------------------------------------------------------------------------------
39 * Constants
40 * --------------------------------------------------------------------------------------------- */
41
42//TODO
43
44/* ------------------------------------------------------------------------------------------------
45 * Static Variables
46 * --------------------------------------------------------------------------------------------- */
47
48//TODO
49
50/* ------------------------------------------------------------------------------------------------
51 * Types
52 * --------------------------------------------------------------------------------------------- */
53
54#[derive(Debug)]
55#[repr(transparent)]
56pub struct ObjectHandle {
57 handle: std::ptr::NonNull<sv_bindings::PLI_UINT32>//We don't want a pointer to a pointer
58}
59
60#[derive(Debug)]
61pub struct ObjectIterator {
62 iterator_handle: Option<ObjectHandle>
63}
64
65#[derive(Clone, Copy, Debug)]
66#[repr(i32)]
67pub enum ObjectType {
68 Always = sv_bindings::vpiAlways, // always procedure
69 AssignStmt = sv_bindings::vpiAssignStmt, // quasi-continuous assignment
70 Assignment = sv_bindings::vpiAssignment, // procedural assignment
71 Begin = sv_bindings::vpiBegin, // block statement
72 Case = sv_bindings::vpiCase, // case statement
73 CaseItem = sv_bindings::vpiCaseItem, // case statement item
74 Constant = sv_bindings::vpiConstant, // numerical constant or string literal
75 ContAssign = sv_bindings::vpiContAssign, // continuous assignment
76 Deassign = sv_bindings::vpiDeassign, // deassignment statement
77 DefParam = sv_bindings::vpiDefParam, // defparam
78 DelayControl = sv_bindings::vpiDelayControl, // delay statement (e.g., #10)
79 Disable = sv_bindings::vpiDisable, // named block disable statement
80 EventControl = sv_bindings::vpiEventControl, // wait on event, e.g., @e
81 EventStmt = sv_bindings::vpiEventStmt, // event trigger, e.g., ->e
82 For = sv_bindings::vpiFor, // for statement
83 Force = sv_bindings::vpiForce, // force statement
84 Forever = sv_bindings::vpiForever, // forever statement
85 Fork = sv_bindings::vpiFork, // fork-join block
86 FuncCall = sv_bindings::vpiFuncCall, // function call
87 Function = sv_bindings::vpiFunction, // function
88 Gate = sv_bindings::vpiGate, // primitive gate
89 If = sv_bindings::vpiIf, // if statement
90 IfElse = sv_bindings::vpiIfElse, // if–else statement
91 Initial = sv_bindings::vpiInitial, // initial procedure
92 IntegerVar = sv_bindings::vpiIntegerVar, // integer variable
93 InterModPath = sv_bindings::vpiInterModPath, // intermodule wire delay
94 Iterator = sv_bindings::vpiIterator, // iterator
95 IODecl = sv_bindings::vpiIODecl, // input/output declaration
96 Memory = sv_bindings::vpiMemory, // behavioral memory
97 MemoryWord = sv_bindings::vpiMemoryWord, // single word of memory
98 ModPath = sv_bindings::vpiModPath, // module path for path delays
99 Module = sv_bindings::vpiModule, // module instance
100 NamedBegin = sv_bindings::vpiNamedBegin, // named block statement
101 NamedEvent = sv_bindings::vpiNamedEvent, // event variable
102 NamedFork = sv_bindings::vpiNamedFork, // named fork-join block
103 Net = sv_bindings::vpiNet, // scalar or vector net
104 NetBit = sv_bindings::vpiNetBit, // bit of vector net
105 NullStmt = sv_bindings::vpiNullStmt, // a semicolon. Ie. #10 ;
106 Operation = sv_bindings::vpiOperation, // behavioral operation
107 ParamAssign = sv_bindings::vpiParamAssign, // module parameter assignment
108 Parameter = sv_bindings::vpiParameter, // module parameter
109 PartSelect = sv_bindings::vpiPartSelect, // part-select
110 PathTerm = sv_bindings::vpiPathTerm, // terminal of module path
111 Port = sv_bindings::vpiPort, // module port
112 PortBit = sv_bindings::vpiPortBit, // bit of vector module port
113 PrimTerm = sv_bindings::vpiPrimTerm, // primitive terminal
114 RealVar = sv_bindings::vpiRealVar, // real variable
115 Reg = sv_bindings::vpiReg, // scalar or vector reg
116 RegBit = sv_bindings::vpiRegBit, // bit of vector reg
117 Release = sv_bindings::vpiRelease, // release statement
118 Repeat = sv_bindings::vpiRepeat, // repeat statement
119 RepeatControl = sv_bindings::vpiRepeatControl, // repeat control in an assign stmt
120 SchedEvent = sv_bindings::vpiSchedEvent, // vpi_put_value() event
121 SpecParam = sv_bindings::vpiSpecParam, // specparam
122 Switch = sv_bindings::vpiSwitch, // transistor switch
123 SysFuncCall = sv_bindings::vpiSysFuncCall, // system function call
124 SysTaskCall = sv_bindings::vpiSysTaskCall, // system task call
125 TableEntry = sv_bindings::vpiTableEntry, // UDP state table entry
126 Task = sv_bindings::vpiTask, // task
127 TaskCall = sv_bindings::vpiTaskCall, // task call
128 Tchk = sv_bindings::vpiTchk, // timing check
129 TchkTerm = sv_bindings::vpiTchkTerm, // terminal of timing check
130 TimeVar = sv_bindings::vpiTimeVar, // time variable
131 TimeQueue = sv_bindings::vpiTimeQueue, // simulation event queue
132 Udp = sv_bindings::vpiUdp, // user-defined primitive
133 UdpDefn = sv_bindings::vpiUdpDefn, // UDP definition
134 UserSystf = sv_bindings::vpiUserSystf, // user-defined system task/function
135 VarSelect = sv_bindings::vpiVarSelect, // variable array selection
136 Wait = sv_bindings::vpiWait, // wait statement
137 While = sv_bindings::vpiWhile, // while statement
138
139 // Object types added with 1364-2001
140 Attribute = sv_bindings::vpiAttribute, // attribute of an object
141 BitSelect = sv_bindings::vpiBitSelect, // Bit-select of parameter, var select
142 Callback = sv_bindings::vpiCallback, // callback object
143 DelayTerm = sv_bindings::vpiDelayTerm, // Delay term which is a load or driver
144 DelayDevice = sv_bindings::vpiDelayDevice, // Delay object within a net
145 Frame = sv_bindings::vpiFrame, // reentrant task/func frame
146 GateArray = sv_bindings::vpiGateArray, // gate instance array
147 ModuleArray = sv_bindings::vpiModuleArray, // module instance array
148 PrimitiveArray = sv_bindings::vpiPrimitiveArray, // vpiprimitiveArray type
149 NetArray = sv_bindings::vpiNetArray, // multidimensional net
150 Range = sv_bindings::vpiRange, // range declaration
151 RegArray = sv_bindings::vpiRegArray, // multidimensional reg
152 SwitchArray = sv_bindings::vpiSwitchArray, // switch instance array
153 UdpArray = sv_bindings::vpiUdpArray, // UDP instance array
154 ContAssignBit = sv_bindings::vpiContAssignBit, // Bit of a vector continuous assignment
155 NamedEventArray = sv_bindings::vpiNamedEventArray, // multidimensional named event
156
157 // Object types added with 1364-2005
158 IndexedPartSelect = sv_bindings::vpiIndexedPartSelect, // Indexed part-select object
159 GenScopeArray = sv_bindings::vpiGenScopeArray, // array of generated scopes
160 GenScope = sv_bindings::vpiGenScope, // A generated scope
161 GenVar = sv_bindings::vpiGenVar, // Object used to instantiate gen scopes
162}
163
164/* ------------------------------------------------------------------------------------------------
165 * Associated Functions and Methods
166 * --------------------------------------------------------------------------------------------- */
167
168impl ObjectIterator {
169 fn new(object_type: ObjectType) -> ObjectIterator {
170 startup::panic_if_in_startup_routine!();
171 //FIXME justify safety
172 let raw_handle = unsafe { sv_bindings::vpi_iterate(object_type as i32, std::ptr::null_mut()) };
173
174 let iterator_handle = if raw_handle.is_null() {
175 None
176 } else {
177 Some(ObjectHandle { handle: std::ptr::NonNull::new(raw_handle).unwrap() })
178 };
179
180 ObjectIterator {
181 iterator_handle: iterator_handle
182 }
183 }
184
185 fn new_with_reference(object_type: ObjectType, reference: &mut ObjectHandle) -> ObjectIterator {
186 startup::panic_if_in_startup_routine!();
187 //FIXME justify safety
188 let raw_handle = unsafe { sv_bindings::vpi_iterate(object_type as i32, reference.handle.as_ptr()) };
189
190 let iterator_handle = if raw_handle.is_null() {
191 None
192 } else {
193 Some(ObjectHandle { handle: std::ptr::NonNull::new(raw_handle).unwrap() })
194 };
195
196 ObjectIterator {
197 iterator_handle: iterator_handle
198 }
199 }
200}
201
202/* ------------------------------------------------------------------------------------------------
203 * Traits And Default Implementations
204 * --------------------------------------------------------------------------------------------- */
205
206//TODO
207
208/* ------------------------------------------------------------------------------------------------
209 * Trait Implementations
210 * --------------------------------------------------------------------------------------------- */
211
212impl Drop for ObjectHandle {
213 fn drop(&mut self) {
214 //Guaranteed the handle is not null (it is a NonNull)
215 //FIXME test this on a simulator that supports it
216 /*
217 unsafe {
218 //FIXME justify safety
219 sv_bindings::vpi_release_handle(handle.as_ptr());
220 }
221 */
222 }
223}
224
225impl Iterator for ObjectIterator {
226 type Item = ObjectHandle;
227
228 fn next(&mut self) -> Option<ObjectHandle> {
229 let unwrapped_iterator_handle = self.iterator_handle.as_mut()?;
230
231 //FIXME justify safety
232 let raw_handle_from_scan = unsafe {
233 sv_bindings::vpi_scan(unwrapped_iterator_handle.handle.as_ptr())
234 };
235
236 if raw_handle_from_scan.is_null() {
237 //FIXME I actually don't think we should release the iterator handle in this case (scan
238 //being null already takes care of that)
239 self.iterator_handle = None;//Iterator handle is now invalid (this drops it)
240 None
241 } else {
242 Some(ObjectHandle { handle: std::ptr::NonNull::new(raw_handle_from_scan).unwrap() })
243 }
244 }
245}
246
247/* ------------------------------------------------------------------------------------------------
248 * Functions
249 * --------------------------------------------------------------------------------------------- */
250
251//TESTING
252/*
253static mut START_OF_SIM_CALLBACK_DATA: sv_bindings::t_cb_data = sv_bindings::t_cb_data {
254 reason: sv_bindings::cbAtStartOfSimTime as i32,
255 cb_rtn: None,//Some(start_of_sim_callback),
256 obj: std::ptr::null_mut(),
257 time: std::ptr::null_mut(),
258 //time: unsafe { &mut VPI_TIME },//Doesn't work :(
259 value: std::ptr::null_mut(),
260 index: 0,
261 user_data: std::ptr::null_mut()
262};
263vlog_startup_routines!(test123);
264fn test123() {
265 //sim_println!("Hello World!");//Illegal to do this
266 unsafe {
267 //START_OF_SIM_CALLBACK_DATA.time = &mut VPI_TIME;//To overcome :(
268
269 //TODO add a callback wrapper to clean up the struct at the end/give it back to user code
270 //(basically consume the box and pass the whole boxed START_OF_SIM_CALLBACK_DATA to the user
271 //after removing the box to avoid memleaks)
272 let time = Time::SimTime{high: 1, low: 2};
273 let ctime: sv_bindings::t_vpi_time = time.into();
274 let ctimebox = Box::new(ctime);
275 START_OF_SIM_CALLBACK_DATA.time = Box::into_raw(ctimebox);
276
277 //TODO in the wrapper around the registration callback panic if SupressTime or Time is NULL
278 sv_bindings::vpi_register_cb(
279 &mut START_OF_SIM_CALLBACK_DATA
280 );
281 }
282}
283static mut VPI_TIME: sv_bindings::t_vpi_time = sv_bindings::t_vpi_time {
284 type_: sv_bindings::vpiSimTime as i32,
285 low: 1,
286 high: 2,
287 real: 0.0,
288};
289extern "C" fn start_of_sim_callback(callback_data_ptr: *mut sv_bindings::t_cb_data) -> sv_bindings::PLI_INT32 {
290 sim_println!("In start_of_sim_callback");
291 for mut module_handle in ObjectIterator::new(ObjectType::Module) {
292
293 //Get the name
294 let name = unsafe { std::ffi::CStr::from_ptr(sv_bindings::vpi_get_str(
295 sv_bindings::vpiName as i32,
296 module_handle.handle.as_ptr()
297 )) }.to_string_lossy().into_owned();
298 sim_println!("Module \"{}\" discovered, handle: {:?}.", name, module_handle);
299
300 sim_println!("Let's see if it contains any modules (only one level deep):");
301 for submodule_handle in ObjectIterator::new_with_reference(ObjectType::Module, &mut module_handle) {
302 let name = unsafe { std::ffi::CStr::from_ptr(sv_bindings::vpi_get_str(
303 sv_bindings::vpiName as i32,
304 submodule_handle.handle.as_ptr()
305 )) }.to_string_lossy().into_owned();
306 sim_println!(" Module \"{}\" discovered, handle: {:?}.", name, submodule_handle);
307 }
308
309 sim_println!("Let's see if it contains any registers (only one level deep):");
310 for net_handle in ObjectIterator::new_with_reference(ObjectType::Reg, &mut module_handle) {
311 let name = unsafe { std::ffi::CStr::from_ptr(sv_bindings::vpi_get_str(
312 sv_bindings::vpiName as i32,
313 net_handle.handle.as_ptr()
314 )) }.to_string_lossy().into_owned();
315 sim_println!(" Net \"{}\" discovered, handle: {:?}.", name, net_handle);
316 }
317 }
318 sim_println!("Simulator info: {:?}", get_simulator_info());
319 0
320}
321*/
322//End of TESTING
323
324
325/* ------------------------------------------------------------------------------------------------
326 * Tests
327 * --------------------------------------------------------------------------------------------- */
328
329//TODO
330
331/* ------------------------------------------------------------------------------------------------
332 * Benchmarks
333 * --------------------------------------------------------------------------------------------- */
334
335//TODO