start adding ExternModuleSimulation

This commit is contained in:
Jacob Lifshay 2025-03-19 17:11:41 -07:00
parent 920d8d875f
commit 6e0016b370
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
5 changed files with 150 additions and 5 deletions

View file

@ -2258,6 +2258,7 @@ impl<'a> Exporter<'a> {
ModuleBody::Extern(ExternModuleBody {
verilog_name,
parameters,
simulation: _,
}) => {
let verilog_name = Ident(verilog_name);
writeln!(body, "{indent}defname = {verilog_name}").unwrap();

View file

@ -21,6 +21,7 @@ use crate::{
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
reg::Reg,
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
sim::{ExternModuleSimGenerator, ExternModuleSimulation},
source_location::SourceLocation,
ty::{CanonicalType, Type},
util::ScopedRef,
@ -1081,6 +1082,7 @@ pub struct ExternModuleBody<
> {
pub verilog_name: Interned<str>,
pub parameters: P,
pub simulation: Option<ExternModuleSimulation<Bundle>>,
}
impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
@ -1088,11 +1090,13 @@ impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
let ExternModuleBody {
verilog_name,
parameters,
simulation,
} = value;
let parameters = Intern::intern_owned(parameters);
Self {
verilog_name,
parameters,
simulation,
}
}
}
@ -1283,10 +1287,12 @@ impl<T: BundleType> fmt::Debug for DebugModuleBody<T> {
ModuleBody::Extern(ExternModuleBody {
verilog_name,
parameters,
simulation,
}) => {
debug_struct
.field("verilog_name", verilog_name)
.field("parameters", parameters);
.field("parameters", parameters)
.field("simulation", simulation);
}
}
debug_struct.finish_non_exhaustive()
@ -1761,7 +1767,12 @@ impl AssertValidityState {
ModuleBody::Extern(ExternModuleBody {
verilog_name: _,
parameters: _,
}) => {}
simulation,
}) => {
if let Some(simulation) = simulation {
simulation.check_io_ty(self.module.io_ty);
}
}
ModuleBody::Normal(NormalModuleBody { body }) => {
let body = self.make_block_index(body);
assert_eq!(body, 0);
@ -2108,6 +2119,7 @@ impl ModuleBuilder {
ModuleKind::Extern => ModuleBody::Extern(ExternModuleBody {
verilog_name: name.0,
parameters: vec![],
simulation: None,
}),
ModuleKind::Normal => ModuleBody::Normal(NormalModuleBody {
body: BuilderModuleBody {
@ -2229,6 +2241,15 @@ impl ModuleBuilder {
value: ExternModuleParameterValue::RawVerilog(raw_verilog.intern()),
});
}
#[track_caller]
pub fn extern_module_simulation<G: ExternModuleSimGenerator>(&self, generator: G) {
let mut impl_ = self.impl_.borrow_mut();
let simulation = &mut impl_.body.builder_extern_body().simulation;
if simulation.is_some() {
panic!("already added an extern module simulation");
}
*simulation = Some(ExternModuleSimulation::new(generator));
}
}
#[track_caller]

View file

@ -31,6 +31,7 @@ use crate::{
phantom_const::PhantomConst,
reg::Reg,
reset::{AsyncReset, Reset, ResetType, SyncReset},
sim::ExternModuleSimulation,
source_location::SourceLocation,
ty::{CanonicalType, Type},
wire::Wire,

View file

@ -15,7 +15,9 @@ use crate::{
ExprEnum, Flow, ToLiteralBits,
},
int::{BoolOrIntType, IntType, SIntValue, UIntValue},
intern::{Intern, Interned, Memoize},
intern::{
Intern, Interned, InternedCompare, Memoize, PtrEqWithTypeId, SupportsPtrEqWithTypeId,
},
memory::PortKind,
module::{
transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, Id, InstantiatedModule,
@ -51,7 +53,15 @@ use petgraph::{
},
};
use std::{
borrow::Cow, collections::BTreeSet, fmt, marker::PhantomData, mem, ops::IndexMut, sync::Arc,
any::Any,
borrow::Cow,
collections::BTreeSet,
fmt,
future::{Future, IntoFuture},
marker::PhantomData,
mem,
ops::IndexMut,
sync::Arc,
};
mod interpreter;
@ -7386,3 +7396,108 @@ impl<T: BundleType> Simulation<T> {
});
}
}
#[derive(Debug)]
pub struct ExternModuleSimulationState<T: BundleType> {
io_ty: T,
}
impl<T: BundleType> ExternModuleSimulationState<T> {
pub fn canonical(self) -> ExternModuleSimulationState<Bundle> {
ExternModuleSimulationState {
io_ty: Bundle::from_canonical(self.io_ty.canonical()),
}
}
pub fn from_canonical(sim: ExternModuleSimulationState<Bundle>) -> Self {
Self {
io_ty: T::from_canonical(sim.io_ty.canonical()),
}
}
}
pub trait ExternModuleSimGenerator:
Clone + Eq + std::hash::Hash + Any + Send + Sync + fmt::Debug
{
type IOType: BundleType;
fn run<'a>(
&'a self,
sim: ExternModuleSimulationState<Self::IOType>,
) -> impl IntoFuture<Output = ()> + 'a;
}
trait DynExternModuleSimGenerator: Any + Send + Sync + SupportsPtrEqWithTypeId + fmt::Debug {
fn dyn_run<'a>(
&'a self,
sim: ExternModuleSimulationState<Bundle>,
) -> Box<dyn Future<Output = ()> + 'a>;
#[track_caller]
fn check_io_ty(&self, io_ty: Bundle);
}
impl<T: ExternModuleSimGenerator> DynExternModuleSimGenerator for T {
fn dyn_run<'a>(
&'a self,
sim: ExternModuleSimulationState<Bundle>,
) -> Box<dyn Future<Output = ()> + 'a> {
Box::new(
self.run(ExternModuleSimulationState::from_canonical(sim))
.into_future(),
)
}
#[track_caller]
fn check_io_ty(&self, io_ty: Bundle) {
T::IOType::from_canonical(io_ty.canonical());
}
}
impl InternedCompare for dyn DynExternModuleSimGenerator {
type InternedCompareKey = PtrEqWithTypeId;
fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey {
this.get_ptr_eq_with_type_id()
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct ExternModuleSimulation<T: BundleType> {
generator: Interned<dyn DynExternModuleSimGenerator>,
_phantom: PhantomData<T>,
}
impl<T: BundleType> ExternModuleSimulation<T> {
pub fn new<G: ExternModuleSimGenerator>(generator: G) -> Self {
Self {
generator: Interned::cast_unchecked(
generator.intern(),
|v| -> &dyn DynExternModuleSimGenerator { v },
),
_phantom: PhantomData,
}
}
pub fn canonical(self) -> ExternModuleSimulation<Bundle> {
ExternModuleSimulation {
generator: self.generator,
_phantom: PhantomData,
}
}
pub fn from_canonical(v: ExternModuleSimulation<Bundle>) -> Self {
Self {
generator: v.generator,
_phantom: PhantomData,
}
}
}
impl ExternModuleSimulation<Bundle> {
fn run<'a>(
&'a self,
sim: ExternModuleSimulationState<Bundle>,
) -> Box<dyn Future<Output = ()> + 'a> {
self.generator.dyn_run(sim)
}
#[track_caller]
pub fn check_io_ty(self, io_ty: Bundle) {
self.generator.check_io_ty(io_ty);
}
}

View file

@ -160,7 +160,8 @@
"data": {
"$kind": "Struct",
"verilog_name": "Visible",
"parameters": "Visible"
"parameters": "Visible",
"simulation": "Visible"
}
},
"ExternModuleParameter": {
@ -1269,6 +1270,12 @@
"$kind": "Opaque"
},
"generics": "<T: ?Sized + crate::phantom_const::PhantomConstValue>"
},
"ExternModuleSimulation": {
"data": {
"$kind": "Opaque"
},
"generics": "<T: BundleType>"
}
}
}