diff --git a/crates/fayalite/src/memory.rs b/crates/fayalite/src/memory.rs index 4992cd6..f583a8c 100644 --- a/crates/fayalite/src/memory.rs +++ b/crates/fayalite/src/memory.rs @@ -22,7 +22,7 @@ use std::{ fmt, hash::{Hash, Hasher}, marker::PhantomData, - num::NonZeroUsize, + num::NonZeroU32, rc::Rc, }; @@ -478,7 +478,7 @@ struct MemImpl { initial_value: Option>, ports: P, read_latency: usize, - write_latency: NonZeroUsize, + write_latency: NonZeroU32, read_under_write: ReadUnderWrite, port_annotations: Interned<[TargetedAnnotation]>, mem_annotations: Interned<[Annotation]>, @@ -562,7 +562,7 @@ impl Mem { initial_value: Option>, ports: Interned<[MemPort]>, read_latency: usize, - write_latency: NonZeroUsize, + write_latency: NonZeroU32, read_under_write: ReadUnderWrite, port_annotations: Interned<[TargetedAnnotation]>, mem_annotations: Interned<[Annotation]>, @@ -645,7 +645,7 @@ impl Mem { pub fn read_latency(self) -> usize { self.0.read_latency } - pub fn write_latency(self) -> NonZeroUsize { + pub fn write_latency(self) -> NonZeroU32 { self.0.write_latency } pub fn read_under_write(self) -> ReadUnderWrite { @@ -707,7 +707,7 @@ pub(crate) struct MemBuilderTarget { pub(crate) initial_value: Option>, pub(crate) ports: Vec>, pub(crate) read_latency: usize, - pub(crate) write_latency: NonZeroUsize, + pub(crate) write_latency: NonZeroU32, pub(crate) read_under_write: ReadUnderWrite, pub(crate) port_annotations: Vec, pub(crate) mem_annotations: Vec, @@ -867,7 +867,7 @@ impl MemBuilder { initial_value: None, ports: vec![], read_latency: 0, - write_latency: NonZeroUsize::new(1).unwrap(), + write_latency: NonZeroU32::new(1).unwrap(), read_under_write: ReadUnderWrite::Old, port_annotations: vec![], mem_annotations: vec![], @@ -1030,10 +1030,10 @@ impl MemBuilder { pub fn read_latency(&mut self, read_latency: usize) { self.target.borrow_mut().read_latency = read_latency; } - pub fn get_write_latency(&self) -> NonZeroUsize { + pub fn get_write_latency(&self) -> NonZeroU32 { self.target.borrow().write_latency } - pub fn write_latency(&mut self, write_latency: NonZeroUsize) { + pub fn write_latency(&mut self, write_latency: NonZeroU32) { self.target.borrow_mut().write_latency = write_latency; } pub fn get_read_under_write(&self) -> ReadUnderWrite { diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index d2906e1..321ab49 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -26,12 +26,12 @@ use crate::{ reset::{ResetType, ResetTypeDispatch}, sim::{ interpreter::{ - Insn, InsnField, InsnFieldKind, InsnFieldType, InsnOrLabel, Insns, InsnsBuilding, - InsnsBuildingDone, InsnsBuildingKind, Label, SlotDebugData, SmallUInt, State, - StatePartArrayIndex, StatePartArrayIndexed, StatePartIndex, StatePartIndexRange, - StatePartKind, StatePartKindBigSlots, StatePartKindMemories, StatePartKindSmallSlots, - StatePartLayout, StatePartLen, StatePartsValue, TypeArrayIndex, TypeArrayIndexes, - TypeIndex, TypeIndexRange, TypeLayout, TypeLen, TypeParts, + Insn, InsnField, InsnFieldKind, InsnFieldType, Insns, InsnsBuilding, InsnsBuildingDone, + SlotDebugData, SmallUInt, State, StatePartArrayIndex, StatePartArrayIndexed, + StatePartIndex, StatePartIndexRange, StatePartKind, StatePartKindBigSlots, + StatePartKindMemories, StatePartKindSmallSlots, StatePartLayout, StatePartLen, + StatePartsValue, TypeArrayIndex, TypeArrayIndexes, TypeIndex, TypeIndexRange, + TypeLayout, TypeLen, TypeParts, }, time::{SimDuration, SimInstant}, }, @@ -970,7 +970,7 @@ struct Assignment { inputs: SlotSet, outputs: SlotSet, conditions: Interned<[Cond]>, - insns: Vec, + insns: Vec, source_location: SourceLocation, } @@ -1116,16 +1116,12 @@ impl<'a> Extend<&'a SlotSet> for SlotToAssignmentIndexFullMapKeysForAssignment<' impl Assignment { fn new( conditions: Interned<[Cond]>, - insns: Vec, + insns: Vec, source_location: SourceLocation, ) -> Self { let mut inputs = SlotSet::default(); let mut outputs = SlotSet::default(); for insn in &insns { - let insn = match insn { - InsnOrLabel::Insn(insn) => insn, - InsnOrLabel::Label(_) => continue, - }; for InsnField { ty, kind } in insn.fields() { match (kind, ty) { (InsnFieldKind::Input, InsnFieldType::SmallSlot(&slot)) => { @@ -1224,29 +1220,11 @@ struct MemoryPort { clk_triggered: StatePartIndex, addr_delayed: Vec>, en_delayed: Vec>, - data_layout: CompiledTypeLayout, - read_data_delayed: Vec, - write_data_delayed: Vec, - write_mask_delayed: Vec, + data: CompiledValue, + read_data_delayed: Vec, + write_data_delayed: Vec, + write_mask_delayed: Vec, write_mode_delayed: Vec>, - write_insns: Vec, -} - -struct MemoryPortReadInsns<'a> { - addr: StatePartIndex, - en: StatePartIndex, - write_mode: Option>, - data: TypeIndexRange, - insns: &'a mut Vec, -} - -struct MemoryPortWriteInsns<'a> { - addr: StatePartIndex, - en: StatePartIndex, - write_mode: Option>, - data: TypeIndexRange, - mask: TypeIndexRange, - insns: &'a mut Vec, } #[derive(Debug)] @@ -1771,13 +1749,13 @@ impl Compiler { self.compiled_exprs_to_values.insert(expr, retval); retval } - fn add_assignment>( + fn add_assignment( &mut self, conditions: Interned<[Cond]>, - insns: impl IntoIterator, + insns: impl IntoIterator, source_location: SourceLocation, ) { - let insns = Vec::from_iter(insns.into_iter().map(Into::into)); + let insns = Vec::from_iter(insns); self.assignments .push(Assignment::new(conditions, insns, source_location)); } @@ -1850,14 +1828,12 @@ impl Compiler { { return retval; } - let mut ty = compiled_value.layout.ty; - ty.width = ty.width.min(SmallUInt::BITS as usize); let retval = match compiled_value.range.len() { TypeLen::A_SMALL_SLOT => compiled_value.range.small_slots.start, TypeLen::A_BIG_SLOT => { let debug_data = SlotDebugData { name: Interned::default(), - ty: ty.canonical(), + ty: UInt::<{ SmallUInt::BITS as usize }>::TYPE.canonical(), }; let dest = self .insns @@ -3348,443 +3324,6 @@ impl Compiler { } self.make_trace_decl(*parent_module, target_base) } - fn allocate_delay_chain( - &mut self, - len: usize, - layout: &TypeLayout, - first: Option, - last: Option, - mut from_allocation: impl FnMut(TypeIndexRange) -> T, - ) -> Vec { - match (len, first, last) { - (0, _, _) => Vec::new(), - (1, Some(v), _) | (1, None, Some(v)) => vec![v], - (2, Some(first), Some(last)) => vec![first, last], - (len, first, last) => { - let inner_len = len - first.is_some() as usize - last.is_some() as usize; - first - .into_iter() - .chain( - (0..inner_len) - .map(|_| from_allocation(self.insns.allocate_variable(layout))), - ) - .chain(last) - .collect() - } - } - } - fn allocate_delay_chain_small( - &mut self, - len: usize, - ty: CanonicalType, - first: Option>, - last: Option>, - ) -> Vec> { - self.allocate_delay_chain( - len, - &TypeLayout { - small_slots: StatePartLayout::scalar( - SlotDebugData { - name: Interned::default(), - ty, - }, - (), - ), - big_slots: StatePartLayout::empty(), - }, - first, - last, - |range| range.small_slots.start, - ) - } - fn compile_memory_port_rw_helper( - &mut self, - memory: StatePartIndex, - stride: usize, - mut start: usize, - data_layout: CompiledTypeLayout, - mask_layout: CompiledTypeLayout, - mut read: Option>, - mut write: Option>, - ) { - match data_layout.body { - CompiledTypeLayoutBody::Scalar => { - let CompiledTypeLayoutBody::Scalar = mask_layout.body else { - unreachable!(); - }; - let signed = match data_layout.ty { - CanonicalType::UInt(_) => false, - CanonicalType::SInt(_) => true, - CanonicalType::Bool(_) => false, - CanonicalType::Array(_) => unreachable!(), - CanonicalType::Enum(_) => false, - CanonicalType::Bundle(_) => unreachable!(), - CanonicalType::AsyncReset(_) => false, - CanonicalType::SyncReset(_) => false, - CanonicalType::Reset(_) => false, - CanonicalType::Clock(_) => false, - }; - let width = data_layout.ty.bit_width(); - if let Some(MemoryPortReadInsns { - addr, - en: _, - write_mode: _, - data, - insns, - }) = read - { - insns.push( - match data.len() { - TypeLen::A_BIG_SLOT => { - let dest = data.big_slots.start; - if signed { - Insn::MemoryReadSInt { - dest, - memory, - addr, - stride, - start, - width, - } - } else { - Insn::MemoryReadUInt { - dest, - memory, - addr, - stride, - start, - width, - } - } - } - TypeLen::A_SMALL_SLOT => { - let _dest = data.small_slots.start; - todo!("memory ports' data are always big for now"); - } - _ => unreachable!(), - } - .into(), - ); - } - if let Some(MemoryPortWriteInsns { - addr, - en: _, - write_mode: _, - data, - mask, - insns, - }) = write - { - let end_label = self.insns.new_label(); - insns.push( - match mask.len() { - TypeLen::A_BIG_SLOT => Insn::BranchIfZero { - target: end_label.0, - value: mask.big_slots.start, - }, - TypeLen::A_SMALL_SLOT => Insn::BranchIfSmallZero { - target: end_label.0, - value: mask.small_slots.start, - }, - _ => unreachable!(), - } - .into(), - ); - insns.push( - match data.len() { - TypeLen::A_BIG_SLOT => { - let dest = data.big_slots.start; - if signed { - Insn::MemoryReadSInt { - dest, - memory, - addr, - stride, - start, - width, - } - } else { - Insn::MemoryReadUInt { - dest, - memory, - addr, - stride, - start, - width, - } - } - } - TypeLen::A_SMALL_SLOT => { - let _dest = data.small_slots.start; - todo!("memory ports' data are always big for now"); - } - _ => unreachable!(), - } - .into(), - ); - insns.push(end_label.into()); - } - } - CompiledTypeLayoutBody::Array { element } => { - let CompiledTypeLayoutBody::Array { - element: mask_element, - } = mask_layout.body - else { - unreachable!(); - }; - let ty = ::from_canonical(data_layout.ty); - let element_bit_width = ty.element().bit_width(); - let element_size = element.layout.len(); - let mask_element_size = mask_element.layout.len(); - for element_index in 0..ty.len() { - self.compile_memory_port_rw_helper( - memory, - stride, - start, - *element, - *mask_element, - read.as_mut().map( - |MemoryPortReadInsns { - addr, - en, - write_mode, - data, - insns, - }| MemoryPortReadInsns { - addr: *addr, - en: *en, - write_mode: *write_mode, - data: data.index_array(element_size, element_index), - insns, - }, - ), - write.as_mut().map( - |MemoryPortWriteInsns { - addr, - en, - write_mode, - data, - mask, - insns, - }| { - MemoryPortWriteInsns { - addr: *addr, - en: *en, - write_mode: *write_mode, - data: data.index_array(element_size, element_index), - mask: mask.index_array(mask_element_size, element_index), - insns, - } - }, - ), - ); - start += element_bit_width; - } - } - CompiledTypeLayoutBody::Bundle { fields } => { - let CompiledTypeLayoutBody::Bundle { - fields: mask_fields, - } = mask_layout.body - else { - unreachable!(); - }; - assert_eq!(fields.len(), mask_fields.len()); - for (field, mask_field) in fields.into_iter().zip(mask_fields) { - let field_index_range = - TypeIndexRange::new(field.offset, field.ty.layout.len()); - let mask_field_index_range = - TypeIndexRange::new(mask_field.offset, mask_field.ty.layout.len()); - self.compile_memory_port_rw_helper( - memory, - stride, - start, - field.ty, - mask_field.ty, - read.as_mut().map( - |MemoryPortReadInsns { - addr, - en, - write_mode, - data, - insns, - }| MemoryPortReadInsns { - addr: *addr, - en: *en, - write_mode: *write_mode, - data: data.slice(field_index_range), - insns, - }, - ), - write.as_mut().map( - |MemoryPortWriteInsns { - addr, - en, - write_mode, - data, - mask, - insns, - }| { - MemoryPortWriteInsns { - addr: *addr, - en: *en, - write_mode: *write_mode, - data: data.slice(field_index_range), - mask: mask.slice(mask_field_index_range), - insns, - } - }, - ), - ); - start = start + field.ty.ty.bit_width(); - } - } - } - } - fn compile_memory_port_rw( - &mut self, - memory: StatePartIndex, - data_layout: CompiledTypeLayout, - mask_layout: CompiledTypeLayout, - mut read: Option>, - mut write: Option>, - ) { - let read_else_label = read.as_mut().map( - |MemoryPortReadInsns { - addr: _, - en, - write_mode, - data: _, - insns, - }| { - let else_label = self.insns.new_label(); - insns.push( - Insn::BranchIfSmallZero { - target: else_label.0, - value: *en, - } - .into(), - ); - if let Some(write_mode) = *write_mode { - insns.push( - Insn::BranchIfSmallNonZero { - target: else_label.0, - value: write_mode, - } - .into(), - ); - } - else_label - }, - ); - let write_end_label = write.as_mut().map( - |MemoryPortWriteInsns { - addr: _, - en, - write_mode, - data: _, - mask: _, - insns, - }| { - let end_label = self.insns.new_label(); - insns.push( - Insn::BranchIfSmallZero { - target: end_label.0, - value: *en, - } - .into(), - ); - if let Some(write_mode) = *write_mode { - insns.push( - Insn::BranchIfSmallZero { - target: end_label.0, - value: write_mode, - } - .into(), - ); - } - end_label - }, - ); - self.compile_memory_port_rw_helper( - memory, - data_layout.ty.bit_width(), - 0, - data_layout, - mask_layout, - read.as_mut().map( - |MemoryPortReadInsns { - addr, - en, - write_mode, - data, - insns, - }| MemoryPortReadInsns { - addr: *addr, - en: *en, - write_mode: *write_mode, - data: *data, - insns: *insns, - }, - ), - write.as_mut().map( - |MemoryPortWriteInsns { - addr, - en, - write_mode, - data, - mask, - insns, - }| MemoryPortWriteInsns { - addr: *addr, - en: *en, - write_mode: *write_mode, - data: *data, - mask: *mask, - insns: *insns, - }, - ), - ); - if let ( - Some(else_label), - Some(MemoryPortReadInsns { - addr: _, - en: _, - write_mode: _, - data, - insns, - }), - ) = (read_else_label, read) - { - let end_label = self.insns.new_label(); - insns.push( - Insn::Branch { - target: end_label.0, - } - .into(), - ); - insns.push(else_label.into()); - let TypeIndexRange { - small_slots, - big_slots, - } = data; - for dest in small_slots.iter() { - insns.push(Insn::ConstSmall { dest, value: 0 }.into()); - } - for dest in big_slots.iter() { - insns.push( - Insn::Const { - dest, - value: BigInt::ZERO.intern_sized(), - } - .into(), - ); - } - insns.push(end_label.into()); - } - if let (Some(end_label), Some(write)) = (write_end_label, write) { - write.insns.push(end_label.into()); - } - } fn compile_memory( &mut self, mem: Mem, @@ -3792,22 +3331,6 @@ impl Compiler { conditions: Interned<[Cond]>, trace_decls: &mut Vec, ) { - let data_layout = CompiledTypeLayout::get(mem.array_type().element()); - let mask_layout = CompiledTypeLayout::get(mem.array_type().element().mask_type()); - let read_latency_plus_1 = mem - .read_latency() - .checked_add(1) - .expect("read latency too big"); - let write_latency_plus_1 = mem - .write_latency() - .get() - .checked_add(1) - .expect("write latency too big"); - let read_cycle = match mem.read_under_write() { - ReadUnderWrite::Old => 0, - ReadUnderWrite::New => mem.read_latency(), - ReadUnderWrite::Undefined => mem.read_latency() / 2, // something other than Old or New - }; let memory = self .insns .state_layout @@ -3833,188 +3356,42 @@ impl Compiler { }; self.decl_conditions.insert(target, conditions); trace_decls.push(self.make_trace_decl(instantiated_module, target_base)); - let clk = Expr::field(port.to_expr(), "clk"); - let clk = self.compile_expr(instantiated_module, clk); - let clk = self.compiled_expr_to_value(clk, mem.source_location()); - let clk_triggered = self - .compile_clock(clk.map_ty(Clock::from_canonical), mem.source_location()) - .clk_triggered; - let en = Expr::field(port.to_expr(), "en"); - let en = self.compile_expr(instantiated_module, en); - let en = self.compiled_expr_to_value(en, mem.source_location()); - let en = self.compiled_value_bool_dest_is_small(en, mem.source_location()); - let addr = Expr::field(port.to_expr(), "addr"); - let addr = self.compile_expr(instantiated_module, addr); - let addr = self.compiled_expr_to_value(addr, mem.source_location()); - let addr_ty = addr.layout.ty; - let addr = self.compiled_value_to_dyn_array_index( - addr.map_ty(UInt::from_canonical), - mem.source_location(), - ); - let read_data = port.port_kind().rdata_name().map(|name| { - let read_data = - self.compile_expr(instantiated_module, Expr::field(port.to_expr(), name)); - let read_data = self.compiled_expr_to_value(read_data, mem.source_location()); - read_data.range - }); - let write_data = port.port_kind().wdata_name().map(|name| { - let write_data = - self.compile_expr(instantiated_module, Expr::field(port.to_expr(), name)); - let write_data = self.compiled_expr_to_value(write_data, mem.source_location()); - write_data.range - }); - let write_mask = port.port_kind().wmask_name().map(|name| { - let write_mask = - self.compile_expr(instantiated_module, Expr::field(port.to_expr(), name)); - let write_mask = self.compiled_expr_to_value(write_mask, mem.source_location()); - write_mask.range - }); - let write_mode = port.port_kind().wmode_name().map(|name| { - let write_mode = - self.compile_expr(instantiated_module, Expr::field(port.to_expr(), name)); - let write_mode = self.compiled_expr_to_value(write_mode, mem.source_location()); - self.compiled_value_bool_dest_is_small(write_mode, mem.source_location()) - }); - struct PortParts { - en_delayed_len: usize, - addr_delayed_len: usize, - read_data_delayed_len: usize, - write_data_delayed_len: usize, - write_mask_delayed_len: usize, - write_mode_delayed_len: usize, - read_cycle: Option, - write_cycle: Option, - } - let PortParts { - en_delayed_len, - addr_delayed_len, - read_data_delayed_len, - write_data_delayed_len, - write_mask_delayed_len, - write_mode_delayed_len, - read_cycle, - write_cycle, - } = match port.port_kind() { - PortKind::ReadOnly => PortParts { - en_delayed_len: read_cycle + 1, - addr_delayed_len: read_cycle + 1, - read_data_delayed_len: read_latency_plus_1 - read_cycle, - write_data_delayed_len: 0, - write_mask_delayed_len: 0, - write_mode_delayed_len: 0, - read_cycle: Some(read_cycle), - write_cycle: None, + match port.port_kind() { + PortKind::ReadOnly => MemoryPort { + clk_triggered: todo!(), + addr_delayed: todo!(), + en_delayed: todo!(), + data: todo!(), + read_data_delayed: todo!(), + write_data_delayed: todo!(), + write_mask_delayed: todo!(), + write_mode_delayed: todo!(), }, - PortKind::WriteOnly => PortParts { - en_delayed_len: write_latency_plus_1, - addr_delayed_len: write_latency_plus_1, - read_data_delayed_len: 0, - write_data_delayed_len: write_latency_plus_1, - write_mask_delayed_len: write_latency_plus_1, - write_mode_delayed_len: 0, - read_cycle: None, - write_cycle: Some(mem.write_latency().get()), + PortKind::WriteOnly => MemoryPort { + clk_triggered: todo!(), + addr_delayed: todo!(), + en_delayed: todo!(), + data: todo!(), + read_data_delayed: todo!(), + write_data_delayed: todo!(), + write_mask_delayed: todo!(), + write_mode_delayed: todo!(), + }, + PortKind::ReadWrite => MemoryPort { + clk_triggered: todo!(), + addr_delayed: todo!(), + en_delayed: todo!(), + data: todo!(), + read_data_delayed: todo!(), + write_data_delayed: todo!(), + write_mask_delayed: todo!(), + write_mode_delayed: todo!(), }, - PortKind::ReadWrite => { - let can_rw_at_end = match mem.read_under_write() { - ReadUnderWrite::Old => false, - ReadUnderWrite::New | ReadUnderWrite::Undefined => true, - }; - let latency_plus_1 = read_latency_plus_1; - if latency_plus_1 != write_latency_plus_1 || !can_rw_at_end { - todo!( - "not sure what to do, issue: \ - https://github.com/chipsalliance/firrtl-spec/issues/263" - ); - } - PortParts { - en_delayed_len: latency_plus_1, - addr_delayed_len: latency_plus_1, - read_data_delayed_len: 1, - write_data_delayed_len: latency_plus_1, - write_mask_delayed_len: latency_plus_1, - write_mode_delayed_len: latency_plus_1, - read_cycle: Some(latency_plus_1 - 1), - write_cycle: Some(latency_plus_1 - 1), - } - } - }; - let addr_delayed = self.allocate_delay_chain_small( - addr_delayed_len, - addr_ty.canonical(), - Some(addr), - None, - ); - let en_delayed = self.allocate_delay_chain_small( - en_delayed_len, - Bool.canonical(), - Some(en), - None, - ); - let read_data_delayed = self.allocate_delay_chain( - read_data_delayed_len, - &data_layout.layout, - None, - read_data, - |v| v, - ); - let write_data_delayed = self.allocate_delay_chain( - write_data_delayed_len, - &data_layout.layout, - write_data, - None, - |v| v, - ); - let write_mask_delayed = self.allocate_delay_chain( - write_mask_delayed_len, - &mask_layout.layout, - write_mask, - None, - |v| v, - ); - let write_mode_delayed = self.allocate_delay_chain_small( - write_mode_delayed_len, - Bool.canonical(), - write_mode, - None, - ); - let mut read_insns = Vec::new(); - let mut write_insns = Vec::new(); - self.compile_memory_port_rw( - memory, - data_layout, - mask_layout, - read_cycle.map(|read_cycle| MemoryPortReadInsns { - addr: addr_delayed[read_cycle], - en: en_delayed[read_cycle], - write_mode: write_mode_delayed.get(read_cycle).copied(), - data: read_data_delayed[0], - insns: &mut read_insns, - }), - write_cycle.map(|write_cycle| MemoryPortWriteInsns { - addr: addr_delayed[write_cycle], - en: en_delayed[write_cycle], - write_mode: write_mode_delayed.get(write_cycle).copied(), - data: write_data_delayed[write_cycle], - mask: write_mask_delayed[write_cycle], - insns: &mut write_insns, - }), - ); - self.add_assignment(Interned::default(), read_insns, mem.source_location()); - MemoryPort { - clk_triggered, - addr_delayed, - en_delayed, - data_layout, - read_data_delayed, - write_data_delayed, - write_mask_delayed, - write_mode_delayed, - write_insns, } }) .collect(); self.memories.push(Memory { mem, memory, ports }); + todo!("implement memory"); } fn compile_block( &mut self, @@ -4172,7 +3549,7 @@ impl Compiler { }; struct CondStackEntry<'a> { cond: &'a Cond, - end_label: Label, + end_label_index: usize, } let mut cond_stack = Vec::>::new(); for assignment_index in assignments_order { @@ -4191,33 +3568,35 @@ impl Compiler { same_len = index + 1; } while cond_stack.len() > same_len { - let CondStackEntry { cond: _, end_label } = - cond_stack.pop().expect("just checked len"); - self.insns.define_label_at_next_insn(end_label); + let CondStackEntry { + cond: _, + end_label_index, + } = cond_stack.pop().expect("just checked len"); + self.insns.define_label_at_next_insn(end_label_index); } for cond in &conditions[cond_stack.len()..] { - let end_label = self.insns.new_label(); + let end_label_index = self.insns.new_label(); match cond.body { CondBody::IfTrue { cond: cond_value } | CondBody::IfFalse { cond: cond_value } => { let (branch_if_zero, branch_if_non_zero) = match cond_value.range.len() { TypeLen::A_SMALL_SLOT => ( Insn::BranchIfSmallZero { - target: end_label.0, + target: end_label_index, value: cond_value.range.small_slots.start, }, Insn::BranchIfSmallNonZero { - target: end_label.0, + target: end_label_index, value: cond_value.range.small_slots.start, }, ), TypeLen::A_BIG_SLOT => ( Insn::BranchIfZero { - target: end_label.0, + target: end_label_index, value: cond_value.range.big_slots.start, }, Insn::BranchIfNonZero { - target: end_label.0, + target: end_label_index, value: cond_value.range.big_slots.start, }, ), @@ -4238,7 +3617,7 @@ impl Compiler { } => { self.insns.push( Insn::BranchIfSmallNeImmediate { - target: end_label.0, + target: end_label_index, lhs: discriminant, rhs: variant_index as _, }, @@ -4246,9 +3625,14 @@ impl Compiler { ); } } - cond_stack.push(CondStackEntry { cond, end_label }); + cond_stack.push(CondStackEntry { + cond, + end_label_index, + }); + } + for insn in insns { + self.insns.push(*insn, *source_location); } - self.insns.extend(insns.iter().copied(), *source_location); } } fn process_clocks(&mut self) -> Interned<[StatePartIndex]> { @@ -4290,11 +3674,11 @@ impl Compiler { let reg_end = self.insns.new_label(); let reg_reset = self.insns.new_label(); let branch_if_reset = Insn::BranchIfSmallNonZero { - target: reg_reset.0, + target: reg_reset, value: rst, }; let branch_if_not_triggered = Insn::BranchIfSmallZero { - target: reg_end.0, + target: reg_end, value: clk_triggered, }; if is_async { @@ -4309,7 +3693,7 @@ impl Compiler { source_location, ); self.insns - .push(Insn::Branch { target: reg_end.0 }, source_location); + .push(Insn::Branch { target: reg_end }, source_location); self.insns.define_label_at_next_insn(reg_reset); self.insns .extend(value.range.insns_for_copy_from(init.range), source_location); @@ -4319,7 +3703,7 @@ impl Compiler { let reg_end = self.insns.new_label(); self.insns.push( Insn::BranchIfSmallZero { - target: reg_end.0, + target: reg_end, value: clk_triggered, }, source_location, @@ -4334,59 +3718,8 @@ impl Compiler { } } fn process_memories(&mut self) { - for Memory { - mem, - memory: _, - ports, - } in mem::take(&mut self.memories) - { - for MemoryPort { - clk_triggered, - addr_delayed, - en_delayed, - data_layout: _, - read_data_delayed, - write_data_delayed, - write_mask_delayed, - write_mode_delayed, - write_insns, - } in ports - { - let port_end = self.insns.new_label(); - self.insns.push( - Insn::BranchIfSmallZero { - target: port_end.0, - value: clk_triggered, - }, - mem.source_location(), - ); - self.insns.extend(write_insns, mem.source_location()); - let small_shift_reg = - |this: &mut Self, values: &[StatePartIndex]| { - for pair in values.windows(2).rev() { - this.insns.push( - Insn::CopySmall { - dest: pair[1], - src: pair[0], - }, - mem.source_location(), - ); - } - }; - let shift_reg = |this: &mut Self, values: &[TypeIndexRange]| { - for pair in values.windows(2).rev() { - this.insns - .extend(pair[0].insns_for_copy_to(pair[1]), mem.source_location()); - } - }; - small_shift_reg(self, &addr_delayed); - small_shift_reg(self, &en_delayed); - shift_reg(self, &read_data_delayed); - shift_reg(self, &write_data_delayed); - shift_reg(self, &write_mask_delayed); - small_shift_reg(self, &write_mode_delayed); - self.insns.define_label_at_next_insn(port_end); - } + for memory in mem::take(&mut self.memories) { + todo!(); } } pub fn compile(mut self) -> Compiled { diff --git a/crates/fayalite/src/sim/interpreter.rs b/crates/fayalite/src/sim/interpreter.rs index 23d1275..0fd0591 100644 --- a/crates/fayalite/src/sim/interpreter.rs +++ b/crates/fayalite/src/sim/interpreter.rs @@ -477,50 +477,14 @@ impl InsnsBuildingKind for InsnsBuilding { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub(crate) struct Label(pub(crate) usize); - -impl fmt::Debug for Label { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "L{}:", self.0) - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub(crate) enum InsnOrLabel { - Insn(Insn), - Label(Label), -} - -impl From for InsnOrLabel { - fn from(value: Insn) -> Self { - Self::Insn(value) - } -} - -impl From