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 {
|
ModuleBody::Extern(ExternModuleBody {
|
||||||
verilog_name,
|
verilog_name,
|
||||||
parameters,
|
parameters,
|
||||||
|
simulation: _,
|
||||||
}) => {
|
}) => {
|
||||||
let verilog_name = Ident(verilog_name);
|
let verilog_name = Ident(verilog_name);
|
||||||
writeln!(body, "{indent}defname = {verilog_name}").unwrap();
|
writeln!(body, "{indent}defname = {verilog_name}").unwrap();
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::{
|
||||||
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
|
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
|
||||||
reg::Reg,
|
reg::Reg,
|
||||||
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
||||||
|
sim::{ExternModuleSimGenerator, ExternModuleSimulation},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
util::ScopedRef,
|
util::ScopedRef,
|
||||||
|
@ -1081,6 +1082,7 @@ pub struct ExternModuleBody<
|
||||||
> {
|
> {
|
||||||
pub verilog_name: Interned<str>,
|
pub verilog_name: Interned<str>,
|
||||||
pub parameters: P,
|
pub parameters: P,
|
||||||
|
pub simulation: Option<ExternModuleSimulation<Bundle>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
|
impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
|
||||||
|
@ -1088,11 +1090,13 @@ impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
|
||||||
let ExternModuleBody {
|
let ExternModuleBody {
|
||||||
verilog_name,
|
verilog_name,
|
||||||
parameters,
|
parameters,
|
||||||
|
simulation,
|
||||||
} = value;
|
} = value;
|
||||||
let parameters = Intern::intern_owned(parameters);
|
let parameters = Intern::intern_owned(parameters);
|
||||||
Self {
|
Self {
|
||||||
verilog_name,
|
verilog_name,
|
||||||
parameters,
|
parameters,
|
||||||
|
simulation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1283,10 +1287,12 @@ impl<T: BundleType> fmt::Debug for DebugModuleBody<T> {
|
||||||
ModuleBody::Extern(ExternModuleBody {
|
ModuleBody::Extern(ExternModuleBody {
|
||||||
verilog_name,
|
verilog_name,
|
||||||
parameters,
|
parameters,
|
||||||
|
simulation,
|
||||||
}) => {
|
}) => {
|
||||||
debug_struct
|
debug_struct
|
||||||
.field("verilog_name", verilog_name)
|
.field("verilog_name", verilog_name)
|
||||||
.field("parameters", parameters);
|
.field("parameters", parameters)
|
||||||
|
.field("simulation", simulation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug_struct.finish_non_exhaustive()
|
debug_struct.finish_non_exhaustive()
|
||||||
|
@ -1761,7 +1767,12 @@ impl AssertValidityState {
|
||||||
ModuleBody::Extern(ExternModuleBody {
|
ModuleBody::Extern(ExternModuleBody {
|
||||||
verilog_name: _,
|
verilog_name: _,
|
||||||
parameters: _,
|
parameters: _,
|
||||||
}) => {}
|
simulation,
|
||||||
|
}) => {
|
||||||
|
if let Some(simulation) = simulation {
|
||||||
|
simulation.check_io_ty(self.module.io_ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
ModuleBody::Normal(NormalModuleBody { body }) => {
|
ModuleBody::Normal(NormalModuleBody { body }) => {
|
||||||
let body = self.make_block_index(body);
|
let body = self.make_block_index(body);
|
||||||
assert_eq!(body, 0);
|
assert_eq!(body, 0);
|
||||||
|
@ -2108,6 +2119,7 @@ impl ModuleBuilder {
|
||||||
ModuleKind::Extern => ModuleBody::Extern(ExternModuleBody {
|
ModuleKind::Extern => ModuleBody::Extern(ExternModuleBody {
|
||||||
verilog_name: name.0,
|
verilog_name: name.0,
|
||||||
parameters: vec![],
|
parameters: vec![],
|
||||||
|
simulation: None,
|
||||||
}),
|
}),
|
||||||
ModuleKind::Normal => ModuleBody::Normal(NormalModuleBody {
|
ModuleKind::Normal => ModuleBody::Normal(NormalModuleBody {
|
||||||
body: BuilderModuleBody {
|
body: BuilderModuleBody {
|
||||||
|
@ -2229,6 +2241,15 @@ impl ModuleBuilder {
|
||||||
value: ExternModuleParameterValue::RawVerilog(raw_verilog.intern()),
|
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]
|
#[track_caller]
|
||||||
|
|
|
@ -31,6 +31,7 @@ use crate::{
|
||||||
phantom_const::PhantomConst,
|
phantom_const::PhantomConst,
|
||||||
reg::Reg,
|
reg::Reg,
|
||||||
reset::{AsyncReset, Reset, ResetType, SyncReset},
|
reset::{AsyncReset, Reset, ResetType, SyncReset},
|
||||||
|
sim::ExternModuleSimulation,
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
wire::Wire,
|
wire::Wire,
|
||||||
|
|
|
@ -15,7 +15,9 @@ use crate::{
|
||||||
ExprEnum, Flow, ToLiteralBits,
|
ExprEnum, Flow, ToLiteralBits,
|
||||||
},
|
},
|
||||||
int::{BoolOrIntType, IntType, SIntValue, UIntValue},
|
int::{BoolOrIntType, IntType, SIntValue, UIntValue},
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{
|
||||||
|
Intern, Interned, InternedCompare, Memoize, PtrEqWithTypeId, SupportsPtrEqWithTypeId,
|
||||||
|
},
|
||||||
memory::PortKind,
|
memory::PortKind,
|
||||||
module::{
|
module::{
|
||||||
transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, Id, InstantiatedModule,
|
transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, Id, InstantiatedModule,
|
||||||
|
@ -51,7 +53,15 @@ use petgraph::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::{
|
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;
|
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": {
|
"data": {
|
||||||
"$kind": "Struct",
|
"$kind": "Struct",
|
||||||
"verilog_name": "Visible",
|
"verilog_name": "Visible",
|
||||||
"parameters": "Visible"
|
"parameters": "Visible",
|
||||||
|
"simulation": "Visible"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ExternModuleParameter": {
|
"ExternModuleParameter": {
|
||||||
|
@ -1269,6 +1270,12 @@
|
||||||
"$kind": "Opaque"
|
"$kind": "Opaque"
|
||||||
},
|
},
|
||||||
"generics": "<T: ?Sized + crate::phantom_const::PhantomConstValue>"
|
"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