pub mod codec;
pub mod covdecl;
pub mod verif;
use crate::collections::FrozenData;
use crate::netlist::{InstanceId, TemplateKey};
use crate::objects::TemplateSnapshot;
use crate::sched::{ProcessKind, SpawnSpec, WaitTableEntry};
use crate::state::{DriveStrengthPair, EdgeKind, FourStateValue, NetKind, StateLayout};
pub const IMAGE_MAGIC: [u8; 8] = *b"VJ-IMAGE";
pub const IMAGE_VERSION: u32 = 58;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum InstanceKind {
Elaborated,
Package,
Bank,
}
#[derive(Clone, Debug, PartialEq)]
pub struct TemplateImage {
pub key: TemplateKey,
pub layout: StateLayout,
}
#[derive(Clone, Debug, PartialEq)]
pub struct InstanceImage {
pub id: InstanceId,
pub template: TemplateKey,
pub kind: InstanceKind,
pub path: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ForeignImage {
pub instance: InstanceId,
pub own_slots: u32,
pub targets: Vec<(InstanceId, u32, Option<crate::state::AliasWindow>)>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct XWindow {
pub instance: InstanceId,
pub slot: u32,
pub value: FourStateValue,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PlaceClass {
Inline,
Wide,
Memory { rows: u32 },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct PlaceImage {
pub instance: InstanceId,
pub slot: u32,
pub width: u32,
pub class: PlaceClass,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct WireImage {
pub src: PlaceImage,
pub src_range: Option<(u32, u32)>,
pub dst: PlaceImage,
pub dst_range: Option<(u32, u32)>,
pub ranged: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DriverImage {
pub slot: u32,
pub strength: DriveStrengthPair,
pub ambiguous: Option<u32>,
pub src: Option<StrengthSrc>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct StrengthSrc {
pub key: u64,
pub bit: u32,
pub out_bit: u32,
pub resistive: bool,
pub tick: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GroupImage {
pub kind: NetKind,
pub width: u32,
pub nets: Vec<(InstanceId, u32)>,
pub drivers: Vec<DriverImage>,
pub switched: bool,
pub decay: Option<u64>,
pub charge: u8,
pub strength_keys: Vec<u64>,
pub strength_tick: Option<u32>,
pub sides: Vec<SideSpec>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SideSpec {
pub key: u64,
pub inside: Vec<bool>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ControlImage {
Bit {
instance: InstanceId,
slot: u32,
width: u32,
bit: u32,
},
Const(u8),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ConductsImage {
Always,
When(ControlImage, bool),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct SwitchImage {
pub a: (u32, u32),
pub b: (u32, u32),
pub conducts: ConductsImage,
pub resistive: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NetworkImage {
pub groups: Vec<u32>,
pub switches: Vec<SwitchImage>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum KernelRole {
Process,
ContAssign,
VarInit,
}
#[derive(Clone, Debug, PartialEq)]
pub struct KernelImage {
pub symbol: u32,
pub frame_words: u32,
pub kind: ProcessKind,
pub instance: InstanceId,
pub role: KernelRole,
pub level_head: bool,
pub reactive: bool,
pub program_initial: bool,
pub registered: bool,
pub read_set: Vec<u32>,
pub read_windows: Vec<(u32, u32, u32)>,
pub reset: Option<(u32, EdgeKind)>,
pub disable_scopes: Vec<(u32, String, u32)>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ForkBranchImage {
pub symbol: u32,
pub frame_words: u32,
pub captures: Vec<(u32, u32)>,
pub disable_scopes: Vec<(u32, String, u32)>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ScopeKind {
Module,
Begin,
Fork,
Task,
Function,
}
impl ScopeKind {
pub fn as_str(self) -> &'static str {
match self {
ScopeKind::Module => "module",
ScopeKind::Begin => "begin",
ScopeKind::Fork => "fork",
ScopeKind::Task => "task",
ScopeKind::Function => "function",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum VcdVarType {
Reg,
Wire,
Integer,
Time,
Real,
RealTime,
Supply0,
Supply1,
Tri,
TriAnd,
TriOr,
TriReg,
Tri0,
Tri1,
WAnd,
WOr,
Event,
}
impl VcdVarType {
pub const ALL: [VcdVarType; 17] = [
VcdVarType::Reg,
VcdVarType::Wire,
VcdVarType::Integer,
VcdVarType::Time,
VcdVarType::Real,
VcdVarType::RealTime,
VcdVarType::Supply0,
VcdVarType::Supply1,
VcdVarType::Tri,
VcdVarType::TriAnd,
VcdVarType::TriOr,
VcdVarType::TriReg,
VcdVarType::Tri0,
VcdVarType::Tri1,
VcdVarType::WAnd,
VcdVarType::WOr,
VcdVarType::Event,
];
pub fn as_str(self) -> &'static str {
match self {
VcdVarType::Reg => "reg",
VcdVarType::Wire => "wire",
VcdVarType::Integer => "integer",
VcdVarType::Time => "time",
VcdVarType::Real => "real",
VcdVarType::RealTime => "realtime",
VcdVarType::Supply0 => "supply0",
VcdVarType::Supply1 => "supply1",
VcdVarType::Tri => "tri",
VcdVarType::TriAnd => "triand",
VcdVarType::TriOr => "trior",
VcdVarType::TriReg => "trireg",
VcdVarType::Tri0 => "tri0",
VcdVarType::Tri1 => "tri1",
VcdVarType::WAnd => "wand",
VcdVarType::WOr => "wor",
VcdVarType::Event => "event",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StmtSiteImage {
pub def: String,
pub buffer: u32,
pub start: u64,
pub end: u64,
pub kind: u16,
pub nest: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FsmImage {
pub instance: InstanceId,
pub name: String,
pub parts: Vec<FsmPartImage>,
pub states: Vec<(String, u64)>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FsmPartImage {
pub slot: u32,
pub msb: u32,
pub lsb: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DumpSignalImage {
pub instance: InstanceId,
pub def_name: String,
pub scope: Vec<String>,
pub scope_kinds: Vec<ScopeKind>,
pub name: String,
pub width: u32,
pub var_type: VcdVarType,
pub slot: u32,
pub wide: bool,
pub real: bool,
pub class_handle: bool,
pub port: Option<PortDir>,
pub strength_key: Option<u64>,
pub side_key: Option<u64>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PortDir {
Input,
Output,
Inout,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct DpiImage {
pub imports: Vec<String>,
pub exports: Vec<(String, u32)>,
pub variants: Vec<(String, String, u32)>,
pub task_fibers: bool,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct TimingOptionsImage {
pub per_bit_vectors: bool,
pub negative_timing_checks: bool,
pub reject_limit_pct: Option<u64>,
pub error_limit_pct: Option<u64>,
pub pulse_style: Option<u8>,
pub showcancelled: Option<bool>,
pub sdf_mtm: Option<u8>,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct TimingImage {
pub options: TimingOptionsImage,
pub plan: Vec<u8>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct DesignImage {
pub abi_version: u32,
pub tick_exp: i32,
pub x_initial_zero: bool,
pub templates: Vec<TemplateImage>,
pub instances: Vec<InstanceImage>,
pub foreign: Vec<ForeignImage>,
pub x_windows: Vec<XWindow>,
pub wires: Vec<WireImage>,
pub groups: Vec<GroupImage>,
pub networks: Vec<NetworkImage>,
pub symbols: Vec<String>,
pub kernels: Vec<KernelImage>,
pub fork_table: Vec<SpawnSpec>,
pub fork_branches: Vec<ForkBranchImage>,
pub wait_table: Vec<WaitTableEntry>,
pub strings: Vec<Vec<u8>>,
pub collections: Vec<FrozenData>,
pub classes: Vec<TemplateSnapshot>,
pub dump_signals: Vec<DumpSignalImage>,
pub stmt_cov: Option<Vec<StmtSiteImage>>,
pub fsms: Vec<FsmImage>,
pub dpi: DpiImage,
pub verif: verif::VerifImage,
pub timing: TimingImage,
pub randomize: Vec<u8>,
pub native_nets: Vec<u8>,
pub vpi: Vec<u8>,
}
impl DesignImage {
pub fn empty(abi_version: u32) -> Self {
DesignImage {
abi_version,
tick_exp: 0,
x_initial_zero: false,
templates: Vec::new(),
instances: Vec::new(),
foreign: Vec::new(),
x_windows: Vec::new(),
wires: Vec::new(),
groups: Vec::new(),
networks: Vec::new(),
symbols: Vec::new(),
kernels: Vec::new(),
fork_table: Vec::new(),
fork_branches: Vec::new(),
wait_table: Vec::new(),
strings: Vec::new(),
collections: Vec::new(),
classes: Vec::new(),
dump_signals: Vec::new(),
stmt_cov: None,
fsms: Vec::new(),
dpi: DpiImage::default(),
verif: verif::VerifImage::default(),
timing: TimingImage::default(),
randomize: Vec::new(),
native_nets: Vec::new(),
vpi: Vec::new(),
}
}
pub fn intern(&mut self, name: &str) -> u32 {
if let Some(i) = self.symbols.iter().position(|s| s == name) {
return i as u32;
}
self.symbols.push(name.to_owned());
(self.symbols.len() - 1) as u32
}
pub fn symbol(&self, index: u32) -> Option<&str> {
self.symbols.get(index as usize).map(String::as_str)
}
pub fn bank(&self) -> Option<InstanceId> {
self.instances
.iter()
.find(|i| i.kind == InstanceKind::Bank)
.map(|i| i.id)
}
pub fn layout_of(&self, key: &TemplateKey) -> Option<&StateLayout> {
self.templates
.iter()
.find(|t| t.key == *key)
.map(|t| &t.layout)
}
}