working on simulator
This commit is contained in:
parent
b288d6f8f2
commit
277d3e0d4d
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -319,6 +319,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"trybuild",
|
"trybuild",
|
||||||
|
"vec_map",
|
||||||
"which",
|
"which",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -720,6 +721,12 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vec_map"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
|
@ -39,4 +39,5 @@ syn = { version = "2.0.66", features = ["full", "fold", "visit", "extra-traits"]
|
||||||
tempfile = "3.10.1"
|
tempfile = "3.10.1"
|
||||||
thiserror = "1.0.61"
|
thiserror = "1.0.61"
|
||||||
trybuild = "1.0"
|
trybuild = "1.0"
|
||||||
|
vec_map = "0.8.2"
|
||||||
which = "6.0.1"
|
which = "6.0.1"
|
||||||
|
|
|
@ -28,6 +28,7 @@ os_pipe.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
tempfile.workspace = true
|
tempfile.workspace = true
|
||||||
|
vec_map.workspace = true
|
||||||
which.workspace = true
|
which.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -4,29 +4,28 @@
|
||||||
//! Fayalite Simulation
|
//! Fayalite Simulation
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bundle::{Bundle, BundleField, BundleType},
|
bundle::{BundleField, BundleType},
|
||||||
enum_::Enum,
|
|
||||||
expr::{
|
expr::{
|
||||||
target::{
|
target::{
|
||||||
Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement,
|
Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement,
|
||||||
},
|
},
|
||||||
Expr,
|
ExprEnum,
|
||||||
},
|
},
|
||||||
int::Bool,
|
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{Intern, Interned, Memoize},
|
||||||
module::{
|
module::{
|
||||||
AnnotatedModuleIO, Block, Instance, Module, ModuleBody, NormalModuleBody, Stmt,
|
AnnotatedModuleIO, Block, ModuleBody, NormalModuleBody, Stmt, StmtConnect, StmtDeclaration,
|
||||||
StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch,
|
StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire,
|
||||||
},
|
},
|
||||||
|
prelude::*,
|
||||||
sim::interpreter::{
|
sim::interpreter::{
|
||||||
Insn, Insns, InsnsBuilding, InsnsBuildingDone, SlotDebugData, StatePartLayout, TypeIndex,
|
Insn, Insns, InsnsBuilding, InsnsBuildingDone, SlotDebugData, SmallUInt, StatePartIndex,
|
||||||
TypeIndexRange, TypeLayout,
|
StatePartIndexMap, StatePartKind, StatePartKindBigSlots, StatePartKindSmallSlots,
|
||||||
|
StatePartLayout, StatePartLen, StatePartsValue, TypeIndex, TypeIndexRange, TypeLayout,
|
||||||
|
TypeLen, TypeParts, MIN_BITS_FOR_NEEDING_BIG,
|
||||||
},
|
},
|
||||||
source_location::SourceLocation,
|
|
||||||
ty::CanonicalType,
|
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::fmt;
|
use std::{fmt, marker::PhantomData, mem};
|
||||||
|
|
||||||
mod interpreter;
|
mod interpreter;
|
||||||
|
|
||||||
|
@ -35,17 +34,17 @@ enum CondStack {
|
||||||
Always,
|
Always,
|
||||||
IfTrue {
|
IfTrue {
|
||||||
parent: Interned<CondStack>,
|
parent: Interned<CondStack>,
|
||||||
cond: Expr<Bool>,
|
cond: CompiledExpr<Bool>,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
},
|
},
|
||||||
IfFalse {
|
IfFalse {
|
||||||
parent: Interned<CondStack>,
|
parent: Interned<CondStack>,
|
||||||
cond: Expr<Bool>,
|
cond: CompiledExpr<Bool>,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
},
|
},
|
||||||
MatchArm {
|
MatchArm {
|
||||||
parent: Interned<CondStack>,
|
parent: Interned<CondStack>,
|
||||||
enum_expr: Expr<Enum>,
|
enum_expr: CompiledExpr<Enum>,
|
||||||
variant_index: usize,
|
variant_index: usize,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
},
|
},
|
||||||
|
@ -95,7 +94,7 @@ struct TargetInInstantiatedModule {
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
struct CompiledBundleField {
|
struct CompiledBundleField {
|
||||||
offset: TypeIndex,
|
offset: TypeIndex,
|
||||||
ty: CompiledTypeLayout,
|
ty: CompiledTypeLayout<CanonicalType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
@ -103,7 +102,7 @@ enum CompiledTypeLayoutBody {
|
||||||
Scalar,
|
Scalar,
|
||||||
Array {
|
Array {
|
||||||
/// debug names are ignored, use parent's layout instead
|
/// debug names are ignored, use parent's layout instead
|
||||||
element: Interned<CompiledTypeLayout>,
|
element: Interned<CompiledTypeLayout<CanonicalType>>,
|
||||||
},
|
},
|
||||||
Bundle {
|
Bundle {
|
||||||
/// debug names are ignored, use parent's layout instead
|
/// debug names are ignored, use parent's layout instead
|
||||||
|
@ -112,13 +111,13 @@ enum CompiledTypeLayoutBody {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
struct CompiledTypeLayout {
|
struct CompiledTypeLayout<T: Type> {
|
||||||
ty: CanonicalType,
|
ty: T,
|
||||||
layout: TypeLayout<InsnsBuildingDone>,
|
layout: TypeLayout<InsnsBuildingDone>,
|
||||||
body: CompiledTypeLayoutBody,
|
body: CompiledTypeLayoutBody,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompiledTypeLayout {
|
impl<T: Type> CompiledTypeLayout<T> {
|
||||||
fn with_prefixed_debug_names(self, prefix: &str) -> Self {
|
fn with_prefixed_debug_names(self, prefix: &str) -> Self {
|
||||||
let Self { ty, layout, body } = self;
|
let Self { ty, layout, body } = self;
|
||||||
Self {
|
Self {
|
||||||
|
@ -127,13 +126,13 @@ impl CompiledTypeLayout {
|
||||||
body,
|
body,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn get(ty: CanonicalType) -> Self {
|
fn get(ty: T) -> Self {
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
struct MyMemoize;
|
struct MyMemoize;
|
||||||
impl Memoize for MyMemoize {
|
impl Memoize for MyMemoize {
|
||||||
type Input = CanonicalType;
|
type Input = CanonicalType;
|
||||||
type InputOwned = CanonicalType;
|
type InputOwned = CanonicalType;
|
||||||
type Output = CompiledTypeLayout;
|
type Output = CompiledTypeLayout<CanonicalType>;
|
||||||
|
|
||||||
fn inner(self, input: &Self::Input) -> Self::Output {
|
fn inner(self, input: &Self::Input) -> Self::Output {
|
||||||
match input {
|
match input {
|
||||||
|
@ -146,8 +145,10 @@ impl CompiledTypeLayout {
|
||||||
| CanonicalType::Reset(_)
|
| CanonicalType::Reset(_)
|
||||||
| CanonicalType::Clock(_) => {
|
| CanonicalType::Clock(_) => {
|
||||||
let mut layout = TypeLayout::empty();
|
let mut layout = TypeLayout::empty();
|
||||||
let debug_data = SlotDebugData { name: "".intern() };
|
let debug_data = SlotDebugData {
|
||||||
if input.bit_width() > interpreter::SmallUInt::BITS as usize {
|
name: Interned::default(),
|
||||||
|
};
|
||||||
|
if input.bit_width() >= interpreter::MIN_BITS_FOR_NEEDING_BIG {
|
||||||
layout.big_slots = StatePartLayout::scalar(debug_data);
|
layout.big_slots = StatePartLayout::scalar(debug_data);
|
||||||
} else {
|
} else {
|
||||||
layout.small_slots = StatePartLayout::scalar(debug_data);
|
layout.small_slots = StatePartLayout::scalar(debug_data);
|
||||||
|
@ -205,24 +206,32 @@ impl CompiledTypeLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MyMemoize.get_owned(ty)
|
let CompiledTypeLayout {
|
||||||
|
ty: _,
|
||||||
|
layout,
|
||||||
|
body,
|
||||||
|
} = MyMemoize.get_owned(ty.canonical());
|
||||||
|
Self { ty, layout, body }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
struct CompiledValue {
|
struct CompiledValue<T: Type> {
|
||||||
layout: CompiledTypeLayout,
|
layout: CompiledTypeLayout<T>,
|
||||||
range: TypeIndexRange,
|
range: TypeIndexRange,
|
||||||
write: Option<(CompiledTypeLayout, TypeIndexRange)>,
|
write: Option<(CompiledTypeLayout<T>, TypeIndexRange)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompiledValue {
|
impl<T: Type> CompiledValue<T> {
|
||||||
fn map(
|
fn map<U: Type>(
|
||||||
self,
|
self,
|
||||||
mut f: impl FnMut(CompiledTypeLayout, TypeIndexRange) -> (CompiledTypeLayout, TypeIndexRange),
|
mut f: impl FnMut(
|
||||||
) -> Self {
|
CompiledTypeLayout<T>,
|
||||||
|
TypeIndexRange,
|
||||||
|
) -> (CompiledTypeLayout<U>, TypeIndexRange),
|
||||||
|
) -> CompiledValue<U> {
|
||||||
let (layout, range) = f(self.layout, self.range);
|
let (layout, range) = f(self.layout, self.range);
|
||||||
Self {
|
CompiledValue {
|
||||||
layout,
|
layout,
|
||||||
range,
|
range,
|
||||||
write: self.write.map(|(layout, range)| f(layout, range)),
|
write: self.write.map(|(layout, range)| f(layout, range)),
|
||||||
|
@ -230,12 +239,98 @@ impl CompiledValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
||||||
|
struct CompiledExprDynIndex {
|
||||||
|
index_slot: StatePartIndex<StatePartKindSmallSlots>,
|
||||||
|
len: TypeLen,
|
||||||
|
stride: TypeLen,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
||||||
|
struct CompiledExpr<T: Type> {
|
||||||
|
static_part: CompiledValue<T>,
|
||||||
|
dyn_indexes: Interned<[CompiledExprDynIndex]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> From<CompiledValue<T>> for CompiledExpr<T> {
|
||||||
|
fn from(static_part: CompiledValue<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
static_part,
|
||||||
|
dyn_indexes: Interned::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> CompiledExpr<T> {
|
||||||
|
fn map_ty<U: Type>(self, mut f: impl FnMut(T) -> U) -> CompiledExpr<U> {
|
||||||
|
let Self {
|
||||||
|
static_part,
|
||||||
|
dyn_indexes,
|
||||||
|
} = self;
|
||||||
|
CompiledExpr {
|
||||||
|
static_part: static_part.map(|CompiledTypeLayout { ty, layout, body }, range| {
|
||||||
|
(
|
||||||
|
CompiledTypeLayout {
|
||||||
|
ty: f(ty),
|
||||||
|
layout,
|
||||||
|
body,
|
||||||
|
},
|
||||||
|
range,
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
dyn_indexes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
|
struct SlotSet(TypeParts<Self>);
|
||||||
|
|
||||||
|
impl SlotSet {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
let Self(TypeParts {
|
||||||
|
small_slots,
|
||||||
|
big_slots,
|
||||||
|
}) = self;
|
||||||
|
small_slots.is_empty() && big_slots.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StatePartsValue for SlotSet {
|
||||||
|
type Value<K: StatePartKind> = Vec<StatePartIndex<K>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Assignment {
|
||||||
|
inputs: SlotSet,
|
||||||
|
insns: Vec<Insn>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct StatePartAssignments<K: StatePartKind> {
|
||||||
|
written_slot_to_assignment_indexes_map: StatePartIndexMap<K, Vec<usize>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct SlotAssignments {
|
||||||
|
assignments: Vec<Assignment>,
|
||||||
|
parts: TypeParts<Self>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StatePartsValue for SlotAssignments {
|
||||||
|
type Value<K: StatePartKind> = StatePartAssignments<K>;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Compiler {
|
pub struct Compiler {
|
||||||
insns: Insns<InsnsBuilding>,
|
insns: Insns<InsnsBuilding>,
|
||||||
base_module: Interned<Module<Bundle>>,
|
base_module: Interned<Module<Bundle>>,
|
||||||
modules: HashMap<InstantiatedModule, CompiledModule>,
|
modules: HashMap<InstantiatedModule, CompiledModule>,
|
||||||
compiled_values: HashMap<TargetInInstantiatedModule, CompiledValue>,
|
compiled_values: HashMap<TargetInInstantiatedModule, CompiledValue<CanonicalType>>,
|
||||||
|
compiled_exprs: HashMap<Expr<CanonicalType>, CompiledExpr<CanonicalType>>,
|
||||||
|
compiled_exprs_to_values: HashMap<CompiledExpr<CanonicalType>, CompiledValue<CanonicalType>>,
|
||||||
|
expanded_to_big: HashMap<Expr<CanonicalType>, CompiledValue<CanonicalType>>,
|
||||||
|
slots_assignments: SlotAssignments,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Compiler {
|
impl Compiler {
|
||||||
|
@ -245,13 +340,20 @@ impl Compiler {
|
||||||
base_module,
|
base_module,
|
||||||
modules: HashMap::new(),
|
modules: HashMap::new(),
|
||||||
compiled_values: HashMap::new(),
|
compiled_values: HashMap::new(),
|
||||||
|
compiled_exprs: HashMap::new(),
|
||||||
|
compiled_exprs_to_values: HashMap::new(),
|
||||||
|
expanded_to_big: HashMap::new(),
|
||||||
|
slots_assignments: SlotAssignments::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn compile_value(&mut self, target: TargetInInstantiatedModule) -> CompiledValue {
|
fn compile_value(
|
||||||
|
&mut self,
|
||||||
|
target: TargetInInstantiatedModule,
|
||||||
|
) -> CompiledValue<CanonicalType> {
|
||||||
if let Some(&retval) = self.compiled_values.get(&target) {
|
if let Some(&retval) = self.compiled_values.get(&target) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
match target.target {
|
let retval = match target.target {
|
||||||
Target::Base(base) => {
|
Target::Base(base) => {
|
||||||
let unprefixed_layout = CompiledTypeLayout::get(base.canonical_ty());
|
let unprefixed_layout = CompiledTypeLayout::get(base.canonical_ty());
|
||||||
let layout = unprefixed_layout.with_prefixed_debug_names(&format!(
|
let layout = unprefixed_layout.with_prefixed_debug_names(&format!(
|
||||||
|
@ -319,7 +421,494 @@ impl Compiler {
|
||||||
TargetPathElement::DynArrayElement(_) => unreachable!(),
|
TargetPathElement::DynArrayElement(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
self.compiled_values.insert(target, retval);
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
fn compiled_expr_to_value(
|
||||||
|
&mut self,
|
||||||
|
expr: CompiledExpr<CanonicalType>,
|
||||||
|
) -> CompiledValue<CanonicalType> {
|
||||||
|
if let Some(&retval) = self.compiled_exprs_to_values.get(&expr) {
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
let CompiledExpr {
|
||||||
|
static_part: mut retval,
|
||||||
|
dyn_indexes,
|
||||||
|
} = expr;
|
||||||
|
for CompiledExprDynIndex {
|
||||||
|
index_slot,
|
||||||
|
len,
|
||||||
|
stride,
|
||||||
|
} in dyn_indexes
|
||||||
|
{
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
self.compiled_exprs_to_values.insert(expr, retval);
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
fn simple_nary_expr<const N: usize>(
|
||||||
|
&mut self,
|
||||||
|
dest_ty: CanonicalType,
|
||||||
|
inputs: [Expr<CanonicalType>; N],
|
||||||
|
make_insns: impl FnOnce(
|
||||||
|
&mut Self,
|
||||||
|
CompiledValue<CanonicalType>,
|
||||||
|
&mut [CompiledValue<CanonicalType>; N],
|
||||||
|
) -> Vec<Insn>,
|
||||||
|
) -> CompiledValue<CanonicalType> {
|
||||||
|
let mut inputs = inputs.map(|input| {
|
||||||
|
let input = self.compile_expr(input);
|
||||||
|
self.compiled_expr_to_value(input)
|
||||||
|
});
|
||||||
|
let layout = CompiledTypeLayout::get(dest_ty);
|
||||||
|
let range = self.insns.allocate_variable(&layout.layout);
|
||||||
|
let retval = CompiledValue {
|
||||||
|
layout,
|
||||||
|
range,
|
||||||
|
write: None,
|
||||||
|
};
|
||||||
|
let insns = make_insns(self, retval, &mut inputs);
|
||||||
|
let mut inputs_set = SlotSet::default();
|
||||||
|
for input in inputs {
|
||||||
|
let TypeIndexRange {
|
||||||
|
small_slots,
|
||||||
|
big_slots,
|
||||||
|
} = input.range;
|
||||||
|
inputs_set.0.small_slots.extend(small_slots.iter());
|
||||||
|
inputs_set.0.big_slots.extend(big_slots.iter());
|
||||||
|
}
|
||||||
|
let assignment_index = self.slots_assignments.assignments.len();
|
||||||
|
self.slots_assignments.assignments.push(Assignment {
|
||||||
|
inputs: inputs_set,
|
||||||
|
insns,
|
||||||
|
});
|
||||||
|
let TypeIndexRange {
|
||||||
|
small_slots,
|
||||||
|
big_slots,
|
||||||
|
} = range;
|
||||||
|
for i in small_slots.iter() {
|
||||||
|
self.slots_assignments
|
||||||
|
.parts
|
||||||
|
.small_slots
|
||||||
|
.written_slot_to_assignment_indexes_map
|
||||||
|
.entry(i)
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(assignment_index);
|
||||||
|
}
|
||||||
|
for i in big_slots.iter() {
|
||||||
|
self.slots_assignments
|
||||||
|
.parts
|
||||||
|
.big_slots
|
||||||
|
.written_slot_to_assignment_indexes_map
|
||||||
|
.entry(i)
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(assignment_index);
|
||||||
|
}
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
fn expand_to_big(&mut self, expr: Expr<CanonicalType>) -> CompiledValue<CanonicalType> {
|
||||||
|
if let Some(&retval) = self.expanded_to_big.get(&expr) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
let input = self.compile_expr(expr);
|
||||||
|
let input = self.compiled_expr_to_value(input);
|
||||||
|
let retval = match input.range.len() {
|
||||||
|
TypeLen {
|
||||||
|
small_slots:
|
||||||
|
StatePartLen {
|
||||||
|
value: 0,
|
||||||
|
_phantom: _,
|
||||||
|
},
|
||||||
|
big_slots: _,
|
||||||
|
} => input,
|
||||||
|
len => {
|
||||||
|
assert_eq!(
|
||||||
|
Some(StatePartLen {
|
||||||
|
value: 1,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}),
|
||||||
|
len.only_small()
|
||||||
|
);
|
||||||
|
let signed = match Expr::ty(expr) {
|
||||||
|
CanonicalType::UInt(_) => false,
|
||||||
|
CanonicalType::SInt(_) => true,
|
||||||
|
CanonicalType::Bool(_) => false,
|
||||||
|
CanonicalType::Enum(_) => false,
|
||||||
|
CanonicalType::Array(_) => unreachable!(),
|
||||||
|
CanonicalType::Bundle(_) => unreachable!(),
|
||||||
|
CanonicalType::AsyncReset(_) => false,
|
||||||
|
CanonicalType::SyncReset(_) => false,
|
||||||
|
CanonicalType::Reset(_) => false,
|
||||||
|
CanonicalType::Clock(_) => false,
|
||||||
|
};
|
||||||
|
self.simple_nary_expr(
|
||||||
|
if signed {
|
||||||
|
SInt::new_dyn(MIN_BITS_FOR_NEEDING_BIG).canonical()
|
||||||
|
} else {
|
||||||
|
UInt::new_dyn(MIN_BITS_FOR_NEEDING_BIG).canonical()
|
||||||
|
},
|
||||||
|
[expr],
|
||||||
|
|_this, dest, [input]| {
|
||||||
|
let dest = dest.range.big_slots.start;
|
||||||
|
let src = input.range.small_slots.start;
|
||||||
|
let unused_bit_count =
|
||||||
|
interpreter::SmallUInt::BITS as u8 - Expr::ty(expr).bit_width() as u8;
|
||||||
|
if signed {
|
||||||
|
vec![Insn::SExtSmallToBig {
|
||||||
|
dest,
|
||||||
|
src,
|
||||||
|
unused_bit_count,
|
||||||
|
}]
|
||||||
|
} else {
|
||||||
|
vec![Insn::ZExtSmallToBig {
|
||||||
|
dest,
|
||||||
|
src,
|
||||||
|
unused_bit_count,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.expanded_to_big.insert(expr, retval);
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
fn simple_nary_small_or_big_expr<const N: usize>(
|
||||||
|
&mut self,
|
||||||
|
dest_ty: CanonicalType,
|
||||||
|
inputs: [Expr<CanonicalType>; N],
|
||||||
|
make_insns_small: impl FnOnce(
|
||||||
|
StatePartIndex<StatePartKindSmallSlots>,
|
||||||
|
[StatePartIndex<StatePartKindSmallSlots>; N],
|
||||||
|
) -> Vec<Insn>,
|
||||||
|
make_insns_big: impl FnOnce(
|
||||||
|
StatePartIndex<StatePartKindBigSlots>,
|
||||||
|
[StatePartIndex<StatePartKindBigSlots>; N],
|
||||||
|
) -> Vec<Insn>,
|
||||||
|
make_insns_big_to_small: impl FnOnce(
|
||||||
|
StatePartIndex<StatePartKindSmallSlots>,
|
||||||
|
[StatePartIndex<StatePartKindBigSlots>; N],
|
||||||
|
) -> Vec<Insn>,
|
||||||
|
) -> CompiledValue<CanonicalType> {
|
||||||
|
self.simple_nary_expr(dest_ty, inputs, |this, dest, compiled_inputs| {
|
||||||
|
let all_inputs_only_small = compiled_inputs
|
||||||
|
.iter()
|
||||||
|
.all(|input| input.range.len().only_small().is_some());
|
||||||
|
if all_inputs_only_small {
|
||||||
|
if dest.range.len().only_small().is_some() {
|
||||||
|
// all small
|
||||||
|
assert_eq!(dest.range.len().small_slots.value, 1);
|
||||||
|
return make_insns_small(
|
||||||
|
dest.range.small_slots.start,
|
||||||
|
compiled_inputs.map(
|
||||||
|
|CompiledValue {
|
||||||
|
layout,
|
||||||
|
range,
|
||||||
|
write: _,
|
||||||
|
}| {
|
||||||
|
assert_eq!(range.small_slots.len().value, 1);
|
||||||
|
range.small_slots.start
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// inputs small, dest big -- expand inputs to big
|
||||||
|
for (&input, compiled_input) in inputs.iter().zip(&mut *compiled_inputs) {
|
||||||
|
*compiled_input = this.expand_to_big(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let big_inputs = compiled_inputs.map(
|
||||||
|
|CompiledValue {
|
||||||
|
layout,
|
||||||
|
range:
|
||||||
|
TypeIndexRange {
|
||||||
|
small_slots,
|
||||||
|
big_slots,
|
||||||
|
},
|
||||||
|
write: _,
|
||||||
|
}| {
|
||||||
|
assert_eq!(small_slots.len().value, 0);
|
||||||
|
assert_eq!(big_slots.len().value, 1);
|
||||||
|
big_slots.start
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if dest.range.len().only_small().is_some() {
|
||||||
|
// inputs big, dest small
|
||||||
|
assert_eq!(dest.range.len().small_slots.value, 1);
|
||||||
|
return make_insns_big_to_small(dest.range.small_slots.start, big_inputs);
|
||||||
|
}
|
||||||
|
let TypeIndexRange {
|
||||||
|
small_slots,
|
||||||
|
big_slots,
|
||||||
|
} = dest.range;
|
||||||
|
assert_eq!(small_slots.len().value, 0);
|
||||||
|
assert_eq!(big_slots.len().value, 1);
|
||||||
|
make_insns_big(big_slots.start, big_inputs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn compile_expr(&mut self, expr: Expr<CanonicalType>) -> CompiledExpr<CanonicalType> {
|
||||||
|
if let Some(&retval) = self.compiled_exprs.get(&expr) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
let retval: CompiledExpr<_> = match *Expr::expr_enum(expr) {
|
||||||
|
ExprEnum::UIntLiteral(expr) => self
|
||||||
|
.simple_nary_small_or_big_expr(
|
||||||
|
Bool.canonical(),
|
||||||
|
[],
|
||||||
|
|dest, []| {
|
||||||
|
vec![Insn::ConstSmall {
|
||||||
|
dest,
|
||||||
|
value: expr.to_bigint().try_into().expect("const too big"),
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
|dest, []| {
|
||||||
|
vec![Insn::ConstBig {
|
||||||
|
dest,
|
||||||
|
value: expr.to_bigint().intern_sized(),
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
|_, _| unreachable!(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
ExprEnum::SIntLiteral(expr) => self
|
||||||
|
.simple_nary_small_or_big_expr(
|
||||||
|
Bool.canonical(),
|
||||||
|
[],
|
||||||
|
|dest, []| {
|
||||||
|
vec![Insn::ConstSmall {
|
||||||
|
dest,
|
||||||
|
value: expr.to_bigint().try_into().expect("const too big"),
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
|dest, []| {
|
||||||
|
vec![Insn::ConstBig {
|
||||||
|
dest,
|
||||||
|
value: expr.to_bigint().intern_sized(),
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
|_, _| unreachable!(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
ExprEnum::BoolLiteral(expr) => self
|
||||||
|
.simple_nary_small_or_big_expr(
|
||||||
|
Bool.canonical(),
|
||||||
|
[],
|
||||||
|
|dest, []| {
|
||||||
|
vec![Insn::ConstSmall {
|
||||||
|
dest,
|
||||||
|
value: expr as SmallUInt,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
|_, _| unreachable!(),
|
||||||
|
|_, _| unreachable!(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
ExprEnum::BundleLiteral(expr) => todo!(),
|
||||||
|
ExprEnum::ArrayLiteral(expr) => todo!(),
|
||||||
|
ExprEnum::EnumLiteral(expr) => todo!(),
|
||||||
|
ExprEnum::Uninit(expr) => todo!(),
|
||||||
|
ExprEnum::NotU(expr) => todo!(),
|
||||||
|
ExprEnum::NotS(expr) => todo!(),
|
||||||
|
ExprEnum::NotB(expr) => todo!(),
|
||||||
|
ExprEnum::Neg(expr) => self
|
||||||
|
.simple_nary_small_or_big_expr(
|
||||||
|
expr.ty().canonical(),
|
||||||
|
[Expr::canonical(expr.arg())],
|
||||||
|
|dest, [src]| vec![Insn::NegSmall { dest, src }],
|
||||||
|
|dest, [src]| vec![Insn::NegBig { dest, src }],
|
||||||
|
|_, _| unreachable!(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
ExprEnum::BitAndU(expr) => todo!(),
|
||||||
|
ExprEnum::BitAndS(expr) => todo!(),
|
||||||
|
ExprEnum::BitAndB(expr) => todo!(),
|
||||||
|
ExprEnum::BitOrU(expr) => todo!(),
|
||||||
|
ExprEnum::BitOrS(expr) => todo!(),
|
||||||
|
ExprEnum::BitOrB(expr) => todo!(),
|
||||||
|
ExprEnum::BitXorU(expr) => todo!(),
|
||||||
|
ExprEnum::BitXorS(expr) => todo!(),
|
||||||
|
ExprEnum::BitXorB(expr) => todo!(),
|
||||||
|
ExprEnum::AddU(expr) => todo!(),
|
||||||
|
ExprEnum::AddS(expr) => todo!(),
|
||||||
|
ExprEnum::SubU(expr) => todo!(),
|
||||||
|
ExprEnum::SubS(expr) => todo!(),
|
||||||
|
ExprEnum::MulU(expr) => todo!(),
|
||||||
|
ExprEnum::MulS(expr) => todo!(),
|
||||||
|
ExprEnum::DivU(expr) => todo!(),
|
||||||
|
ExprEnum::DivS(expr) => todo!(),
|
||||||
|
ExprEnum::RemU(expr) => todo!(),
|
||||||
|
ExprEnum::RemS(expr) => todo!(),
|
||||||
|
ExprEnum::DynShlU(expr) => todo!(),
|
||||||
|
ExprEnum::DynShlS(expr) => todo!(),
|
||||||
|
ExprEnum::DynShrU(expr) => todo!(),
|
||||||
|
ExprEnum::DynShrS(expr) => todo!(),
|
||||||
|
ExprEnum::FixedShlU(expr) => todo!(),
|
||||||
|
ExprEnum::FixedShlS(expr) => todo!(),
|
||||||
|
ExprEnum::FixedShrU(expr) => todo!(),
|
||||||
|
ExprEnum::FixedShrS(expr) => todo!(),
|
||||||
|
ExprEnum::CmpLtB(expr) => todo!(),
|
||||||
|
ExprEnum::CmpLeB(expr) => todo!(),
|
||||||
|
ExprEnum::CmpGtB(expr) => todo!(),
|
||||||
|
ExprEnum::CmpGeB(expr) => todo!(),
|
||||||
|
ExprEnum::CmpEqB(expr) => todo!(),
|
||||||
|
ExprEnum::CmpNeB(expr) => todo!(),
|
||||||
|
ExprEnum::CmpLtU(expr) => todo!(),
|
||||||
|
ExprEnum::CmpLeU(expr) => todo!(),
|
||||||
|
ExprEnum::CmpGtU(expr) => todo!(),
|
||||||
|
ExprEnum::CmpGeU(expr) => todo!(),
|
||||||
|
ExprEnum::CmpEqU(expr) => todo!(),
|
||||||
|
ExprEnum::CmpNeU(expr) => todo!(),
|
||||||
|
ExprEnum::CmpLtS(expr) => todo!(),
|
||||||
|
ExprEnum::CmpLeS(expr) => todo!(),
|
||||||
|
ExprEnum::CmpGtS(expr) => todo!(),
|
||||||
|
ExprEnum::CmpGeS(expr) => todo!(),
|
||||||
|
ExprEnum::CmpEqS(expr) => todo!(),
|
||||||
|
ExprEnum::CmpNeS(expr) => todo!(),
|
||||||
|
ExprEnum::CastUIntToUInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastUIntToSInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastSIntToUInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastSIntToSInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastBoolToUInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastBoolToSInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastUIntToBool(expr) => todo!(),
|
||||||
|
ExprEnum::CastSIntToBool(expr) => todo!(),
|
||||||
|
ExprEnum::CastBoolToSyncReset(expr) => todo!(),
|
||||||
|
ExprEnum::CastUIntToSyncReset(expr) => todo!(),
|
||||||
|
ExprEnum::CastSIntToSyncReset(expr) => todo!(),
|
||||||
|
ExprEnum::CastBoolToAsyncReset(expr) => todo!(),
|
||||||
|
ExprEnum::CastUIntToAsyncReset(expr) => todo!(),
|
||||||
|
ExprEnum::CastSIntToAsyncReset(expr) => todo!(),
|
||||||
|
ExprEnum::CastSyncResetToBool(expr) => todo!(),
|
||||||
|
ExprEnum::CastSyncResetToUInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastSyncResetToSInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastSyncResetToReset(expr) => todo!(),
|
||||||
|
ExprEnum::CastAsyncResetToBool(expr) => todo!(),
|
||||||
|
ExprEnum::CastAsyncResetToUInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastAsyncResetToSInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastAsyncResetToReset(expr) => todo!(),
|
||||||
|
ExprEnum::CastResetToBool(expr) => todo!(),
|
||||||
|
ExprEnum::CastResetToUInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastResetToSInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastBoolToClock(expr) => todo!(),
|
||||||
|
ExprEnum::CastUIntToClock(expr) => todo!(),
|
||||||
|
ExprEnum::CastSIntToClock(expr) => todo!(),
|
||||||
|
ExprEnum::CastClockToBool(expr) => todo!(),
|
||||||
|
ExprEnum::CastClockToUInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastClockToSInt(expr) => todo!(),
|
||||||
|
ExprEnum::FieldAccess(expr) => todo!(),
|
||||||
|
ExprEnum::VariantAccess(expr) => todo!(),
|
||||||
|
ExprEnum::ArrayIndex(expr) => todo!(),
|
||||||
|
ExprEnum::DynArrayIndex(expr) => todo!(),
|
||||||
|
ExprEnum::ReduceBitAndU(expr) => todo!(),
|
||||||
|
ExprEnum::ReduceBitAndS(expr) => todo!(),
|
||||||
|
ExprEnum::ReduceBitOrU(expr) => todo!(),
|
||||||
|
ExprEnum::ReduceBitOrS(expr) => todo!(),
|
||||||
|
ExprEnum::ReduceBitXorU(expr) => todo!(),
|
||||||
|
ExprEnum::ReduceBitXorS(expr) => todo!(),
|
||||||
|
ExprEnum::SliceUInt(expr) => todo!(),
|
||||||
|
ExprEnum::SliceSInt(expr) => todo!(),
|
||||||
|
ExprEnum::CastToBits(expr) => todo!(),
|
||||||
|
ExprEnum::CastBitsTo(expr) => todo!(),
|
||||||
|
ExprEnum::ModuleIO(expr) => todo!(),
|
||||||
|
ExprEnum::Instance(expr) => todo!(),
|
||||||
|
ExprEnum::Wire(expr) => todo!(),
|
||||||
|
ExprEnum::Reg(expr) => todo!(),
|
||||||
|
ExprEnum::MemPort(expr) => todo!(),
|
||||||
|
};
|
||||||
|
self.compiled_exprs.insert(expr, retval);
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
fn compile_connect(
|
||||||
|
&mut self,
|
||||||
|
parent_module: Interned<InstantiatedModule>,
|
||||||
|
cond_stack: Interned<CondStack>,
|
||||||
|
lhs: Expr<CanonicalType>,
|
||||||
|
mut rhs: Expr<CanonicalType>,
|
||||||
|
source_location: SourceLocation,
|
||||||
|
) {
|
||||||
|
if Expr::ty(lhs) != Expr::ty(rhs) || !Expr::ty(lhs).is_passive() {
|
||||||
|
match Expr::ty(lhs) {
|
||||||
|
CanonicalType::UInt(lhs_ty) => {
|
||||||
|
rhs = Expr::canonical(Expr::<UInt>::from_canonical(rhs).cast_to(lhs_ty));
|
||||||
|
}
|
||||||
|
CanonicalType::SInt(lhs_ty) => {
|
||||||
|
rhs = Expr::canonical(Expr::<SInt>::from_canonical(rhs).cast_to(lhs_ty));
|
||||||
|
}
|
||||||
|
CanonicalType::Bool(_) => unreachable!(),
|
||||||
|
CanonicalType::Array(lhs_ty) => {
|
||||||
|
let CanonicalType::Array(rhs_ty) = Expr::ty(rhs) else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
assert_eq!(lhs_ty.len(), rhs_ty.len());
|
||||||
|
let lhs = Expr::<Array>::from_canonical(lhs);
|
||||||
|
let rhs = Expr::<Array>::from_canonical(rhs);
|
||||||
|
for index in 0..lhs_ty.len() {
|
||||||
|
self.compile_connect(
|
||||||
|
parent_module,
|
||||||
|
cond_stack,
|
||||||
|
lhs[index],
|
||||||
|
rhs[index],
|
||||||
|
source_location,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CanonicalType::Enum(lhs_ty) => {
|
||||||
|
let CanonicalType::Enum(rhs_ty) = Expr::ty(rhs) else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
todo!("handle connect with different enum types");
|
||||||
|
}
|
||||||
|
CanonicalType::Bundle(lhs_ty) => {
|
||||||
|
let CanonicalType::Bundle(rhs_ty) = Expr::ty(rhs) else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
assert_eq!(lhs_ty.fields().len(), rhs_ty.fields().len());
|
||||||
|
let lhs = Expr::<Bundle>::from_canonical(lhs);
|
||||||
|
let rhs = Expr::<Bundle>::from_canonical(rhs);
|
||||||
|
for (
|
||||||
|
field_index,
|
||||||
|
(
|
||||||
|
BundleField {
|
||||||
|
name,
|
||||||
|
flipped,
|
||||||
|
ty: _,
|
||||||
|
},
|
||||||
|
rhs_field,
|
||||||
|
),
|
||||||
|
) in lhs_ty.fields().into_iter().zip(rhs_ty.fields()).enumerate()
|
||||||
|
{
|
||||||
|
assert_eq!(name, rhs_field.name);
|
||||||
|
assert_eq!(flipped, rhs_field.flipped);
|
||||||
|
let mut lhs_expr =
|
||||||
|
crate::expr::ops::FieldAccess::new_by_index(lhs, field_index).to_expr();
|
||||||
|
let mut rhs_expr =
|
||||||
|
crate::expr::ops::FieldAccess::new_by_index(rhs, field_index).to_expr();
|
||||||
|
if flipped {
|
||||||
|
mem::swap(&mut lhs_expr, &mut rhs_expr);
|
||||||
|
}
|
||||||
|
self.compile_connect(
|
||||||
|
parent_module,
|
||||||
|
cond_stack,
|
||||||
|
lhs_expr,
|
||||||
|
rhs_expr,
|
||||||
|
source_location,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CanonicalType::AsyncReset(_) => unreachable!(),
|
||||||
|
CanonicalType::SyncReset(_) => unreachable!(),
|
||||||
|
CanonicalType::Reset(_) => unreachable!(),
|
||||||
|
CanonicalType::Clock(_) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let lhs = self.compile_expr(lhs);
|
||||||
|
let rhs = self.compile_expr(rhs);
|
||||||
|
let rhs = self.compiled_expr_to_value(rhs);
|
||||||
|
todo!();
|
||||||
}
|
}
|
||||||
fn compile_block(
|
fn compile_block(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -337,7 +926,7 @@ impl Compiler {
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
source_location,
|
source_location,
|
||||||
}) => todo!(),
|
}) => self.compile_connect(parent_module, cond_stack, lhs, rhs, source_location),
|
||||||
Stmt::Formal(StmtFormal {
|
Stmt::Formal(StmtFormal {
|
||||||
kind,
|
kind,
|
||||||
clk,
|
clk,
|
||||||
|
@ -351,6 +940,9 @@ impl Compiler {
|
||||||
source_location,
|
source_location,
|
||||||
blocks: [then_block, else_block],
|
blocks: [then_block, else_block],
|
||||||
}) => {
|
}) => {
|
||||||
|
let cond = self
|
||||||
|
.compile_expr(Expr::canonical(cond))
|
||||||
|
.map_ty(Bool::from_canonical);
|
||||||
self.compile_block(
|
self.compile_block(
|
||||||
parent_module,
|
parent_module,
|
||||||
then_block,
|
then_block,
|
||||||
|
@ -377,13 +969,16 @@ impl Compiler {
|
||||||
source_location,
|
source_location,
|
||||||
blocks,
|
blocks,
|
||||||
}) => {
|
}) => {
|
||||||
|
let enum_expr = self
|
||||||
|
.compile_expr(Expr::canonical(expr))
|
||||||
|
.map_ty(Enum::from_canonical);
|
||||||
for (variant_index, block) in blocks.into_iter().enumerate() {
|
for (variant_index, block) in blocks.into_iter().enumerate() {
|
||||||
self.compile_block(
|
self.compile_block(
|
||||||
parent_module,
|
parent_module,
|
||||||
block,
|
block,
|
||||||
CondStack::MatchArm {
|
CondStack::MatchArm {
|
||||||
parent: cond_stack,
|
parent: cond_stack,
|
||||||
enum_expr: expr,
|
enum_expr,
|
||||||
variant_index,
|
variant_index,
|
||||||
source_location,
|
source_location,
|
||||||
}
|
}
|
||||||
|
@ -392,19 +987,51 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::Declaration(declaration) => match declaration {
|
Stmt::Declaration(declaration) => match declaration {
|
||||||
StmtDeclaration::Wire(wire) => todo!(),
|
StmtDeclaration::Wire(StmtWire { annotations, wire }) => {
|
||||||
StmtDeclaration::Reg(reg) => todo!(),
|
self.compile_value(TargetInInstantiatedModule {
|
||||||
|
instantiated_module: *parent_module,
|
||||||
|
target: wire.into(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
StmtDeclaration::Reg(StmtReg { annotations, reg }) => {
|
||||||
|
self.compile_value(TargetInInstantiatedModule {
|
||||||
|
instantiated_module: *parent_module,
|
||||||
|
target: reg.into(),
|
||||||
|
});
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
StmtDeclaration::Instance(StmtInstance {
|
StmtDeclaration::Instance(StmtInstance {
|
||||||
annotations,
|
annotations,
|
||||||
instance,
|
instance,
|
||||||
}) => {
|
}) => {
|
||||||
self.compile_module(
|
let CompiledValue {
|
||||||
|
layout:
|
||||||
|
CompiledTypeLayout {
|
||||||
|
ty: value_ty,
|
||||||
|
layout: ty_layout,
|
||||||
|
body: CompiledTypeLayoutBody::Bundle { fields },
|
||||||
|
},
|
||||||
|
range: value_range,
|
||||||
|
write: None,
|
||||||
|
} = self.compile_value(TargetInInstantiatedModule {
|
||||||
|
instantiated_module: *parent_module,
|
||||||
|
target: instance.into(),
|
||||||
|
})
|
||||||
|
else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
let CompiledModule { module_io } = *self.compile_module(
|
||||||
InstantiatedModule::Child {
|
InstantiatedModule::Child {
|
||||||
parent: parent_module,
|
parent: parent_module,
|
||||||
instance: instance.intern_sized(),
|
instance: instance.intern_sized(),
|
||||||
}
|
}
|
||||||
.intern_sized(),
|
.intern_sized(),
|
||||||
);
|
);
|
||||||
|
for (module_io, CompiledBundleField { offset, ty }) in
|
||||||
|
module_io.into_iter().zip(fields)
|
||||||
|
{
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -452,7 +1079,7 @@ impl Compiler {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct CompiledModule {
|
struct CompiledModule {
|
||||||
module_io: Interned<[CompiledValue]>,
|
module_io: Interned<[CompiledValue<CanonicalType>]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,7 +24,8 @@ pub use scoped_ref::ScopedRef;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use misc::{
|
pub use misc::{
|
||||||
interned_bit, iter_eq_by, BitSliceWriteWithBase, DebugAsDisplay, DebugAsRawString, MakeMutSlice,
|
get_many_mut, interned_bit, iter_eq_by, BitSliceWriteWithBase, DebugAsDisplay,
|
||||||
|
DebugAsRawString, MakeMutSlice,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod job_server;
|
pub mod job_server;
|
||||||
|
|
|
@ -155,3 +155,19 @@ impl fmt::UpperHex for BitSliceWriteWithBase<'_> {
|
||||||
self.fmt_with_base::<4, true>(f)
|
self.fmt_with_base::<4, true>(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[track_caller]
|
||||||
|
pub fn get_many_mut<T, const N: usize>(slice: &mut [T], indexes: [usize; N]) -> [&mut T; N] {
|
||||||
|
for i in 0..N {
|
||||||
|
for j in 0..i {
|
||||||
|
assert!(indexes[i] != indexes[j], "duplicate index");
|
||||||
|
}
|
||||||
|
assert!(indexes[i] < slice.len(), "index out of bounds");
|
||||||
|
}
|
||||||
|
// Safety: checked that no indexes are duplicates and no indexes are out of bounds
|
||||||
|
unsafe {
|
||||||
|
let base = slice.as_mut_ptr(); // convert to a raw pointer before loop to avoid aliasing with &mut [T]
|
||||||
|
std::array::from_fn(|i| &mut *base.add(indexes[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue