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