forked from libre-chip/fayalite
start adding ExternModuleSimulation
This commit is contained in:
parent
920d8d875f
commit
6e0016b370
5 changed files with 150 additions and 5 deletions
|
@ -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();
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue