From afec10b2db32221debc8e5539bbdda065a55cb51 Mon Sep 17 00:00:00 2001 From: Lennart Van Hirtum Date: Mon, 1 Jan 2024 19:16:26 +0100 Subject: [PATCH] Arrays can now also be used in Generative Context --- multiply_add.sus | 17 ++++++++++++---- src/flattening.rs | 4 ++++ src/instantiation/mod.rs | 43 ++++++++++++++++++++++++++++++++-------- src/typing.rs | 21 +++++++++++++++++++- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/multiply_add.sus b/multiply_add.sus index 913abab..fe34f62 100644 --- a/multiply_add.sus +++ b/multiply_add.sus @@ -286,15 +286,24 @@ module Unpack4 : int[4] packed -> int out_stream { } } -module generative : int a -> int o { +module generative : int in -> int o, int o2 { gen int x = 5; gen int[x] ys; - gen int[ys] zs; + //gen int[ys] zs; gen int[3] ps; - o = zs[0]; + gen int[3] a; + + a[2] = 5; + a[1] = 2; + a[0] = 10; + gen int[3] xx = a; + + + o = a[in]; + o2 = a[a[1]]; } @@ -327,7 +336,7 @@ module first_bit_idx_24 : bool[24] bits -> int first { int[4] offsets; bool[4] was_nonzero; - for i in 0..4 { + for int i in 0..4 { offsets[i], was_nonzero[i] = first_bit_idx_6(bits[i*6+:6]); } } diff --git a/src/flattening.rs b/src/flattening.rs index 791b3a2..be4ecfc 100644 --- a/src/flattening.rs +++ b/src/flattening.rs @@ -20,6 +20,10 @@ pub enum ConnectionWritePathElement { ArrayIdx(SpanFlatID), //StructField(FieldID) } +#[derive(Debug)] +pub enum ConnectionWritePathElementComputed { + ArrayIdx(usize) +} // These are assignable connections #[derive(Debug)] diff --git a/src/instantiation/mod.rs b/src/instantiation/mod.rs index 7b38bac..04be788 100644 --- a/src/instantiation/mod.rs +++ b/src/instantiation/mod.rs @@ -2,7 +2,7 @@ use std::{rc::Rc, ops::Deref, cell::RefCell}; use num::BigInt; -use crate::{arena_alloc::{UUID, UUIDMarker, FlatAlloc}, ast::{Operator, Module, IdentifierType, Span}, typing::{ConcreteType, Type}, flattening::{FlatID, Instantiation, FlatIDMarker, ConnectionWritePathElement, WireSource, SpanFlatID, WireInstance, Connection}, errors::ErrorCollector, linker::{Linker, get_builtin_uuid}, value::{Value, compute_unary_op, compute_binary_op}}; +use crate::{arena_alloc::{UUID, UUIDMarker, FlatAlloc}, ast::{Operator, Module, IdentifierType, Span}, typing::{ConcreteType, Type}, flattening::{FlatID, Instantiation, FlatIDMarker, ConnectionWritePathElement, WireSource, SpanFlatID, WireInstance, Connection, ConnectionWritePathElementComputed}, errors::ErrorCollector, linker::{Linker, get_builtin_uuid}, value::{Value, compute_unary_op, compute_binary_op}}; pub mod latency; @@ -141,6 +141,18 @@ impl SubModuleOrWire { } } +fn write_gen_variable(mut target : &mut Value, conn_path : &[ConnectionWritePathElementComputed], to_write : Value) { + for elem in conn_path { + match elem { + ConnectionWritePathElementComputed::ArrayIdx(idx) => { + let Value::Array(a_box) = target else {unreachable!()}; + target = &mut a_box[*idx]; + } + } + } + *target = to_write; +} + struct InstantiationContext<'fl, 'l> { generation_state : FlatAlloc, wires : FlatAlloc, @@ -217,6 +229,20 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { sources.push(MultiplexerSource{from, path : new_path}); } + fn convert_connection_path_to_known_values(&self, conn_path : &[ConnectionWritePathElement]) -> Option> { + let mut result = Vec::new(); + result.reserve(conn_path.len()); + for p in conn_path { + match p { + ConnectionWritePathElement::ArrayIdx(idx) => { + let Some(idx_val) = self.get_generation_value(idx) else {return None}; + let Some(idx_val) = self.extract_integer_from_value::(idx_val, idx.1) else {return None}; + result.push(ConnectionWritePathElementComputed::ArrayIdx(idx_val)) + } + } + } + Some(result) + } fn process_connection(&mut self, conn : &Connection, original_wire : FlatID) { match &self.generation_state[conn.to.root] { SubModuleOrWire::SubModule(_) => unreachable!(), @@ -240,9 +266,10 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { } SubModuleOrWire::CompileTimeValue(_original_value) => { // Compiletime wire let found_v = self.generation_state[conn.from.0].extract_generation_value().clone(); + let Some(cvt_path) = self.convert_connection_path_to_known_values(&conn.to.path) else {return}; // Hack to get around the borrow rules here let SubModuleOrWire::CompileTimeValue(v_writable) = &mut self.generation_state[conn.to.root] else {unreachable!()}; - *v_writable = found_v; + write_gen_variable(v_writable, &cvt_path, found_v); } }; @@ -255,11 +282,11 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { None } } - fn compute_compile_time(&self, wire_inst : &WireSource) -> Option { + fn compute_compile_time(&self, wire_inst : &WireSource, typ : &ConcreteType) -> Option { Some(match &wire_inst { WireSource::NamedWire{read_only, identifier_type, decl_id} => { /*Do nothing (in fact re-initializes the wire to 'empty'), just corresponds to wire declaration*/ - Value::Unset + typ.get_initial_val(self.linker) } WireSource::UnaryOp{op, right} => { let right_val = self.get_generation_value(right)?; @@ -307,13 +334,13 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { SubModuleOrWire::SubModule(self.submodules.alloc(SubModule { original_flat: original_wire, instance, wires : interface_real_wires, name : name.clone()})) } Instantiation::Wire(w) => { + let Some(typ) = self.concretize_type(&w.typ, w.span) else { + return; // Exit early, do not produce invalid wires in InstantiatedModule + }; if w.is_compiletime { - let Some(value_computed) = self.compute_compile_time(&w.inst) else {return}; + let Some(value_computed) = self.compute_compile_time(&w.inst, &typ) else {return}; SubModuleOrWire::CompileTimeValue(value_computed) } else { - let Some(typ) = self.concretize_type(&w.typ, w.span) else { - return; // Exit early, do not produce invalid wires in InstantiatedModule - }; let (name, source) = match &w.inst { WireSource::NamedWire{read_only, identifier_type, decl_id} => { let source = if *read_only { diff --git a/src/typing.rs b/src/typing.rs index d896acc..4961006 100644 --- a/src/typing.rs +++ b/src/typing.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use crate::{ast::{Operator, Span}, linker::{get_builtin_uuid, NamedUUID, Linker, Linkable}, tokenizer::kw, flattening::FlatID, errors::ErrorCollector}; +use crate::{ast::{Operator, Span}, linker::{get_builtin_uuid, NamedUUID, Linker, Linkable}, tokenizer::kw, flattening::FlatID, errors::ErrorCollector, value::Value}; // Types contain everything that cannot be expressed at runtime #[derive(Debug, Clone)] @@ -120,3 +120,22 @@ pub enum ConcreteType { Named(NamedUUID), Array(Box<(ConcreteType, u64)>) } + +impl ConcreteType { + pub fn get_initial_val(&self, linker : &Linker) -> Value { + match self { + ConcreteType::Named(_name) => { + Value::Unset + } + ConcreteType::Array(arr) => { + let (arr_typ, arr_size) = arr.deref(); + let mut arr = Vec::new(); + if *arr_size > 0 { + let content_typ = arr_typ.get_initial_val(linker); + arr.resize(*arr_size as usize, content_typ); + } + Value::Array(arr.into_boxed_slice()) + } + } + } +}