Skip to content

Commit

Permalink
Arrays can now also be used in Generative Context
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Jan 1, 2024
1 parent 1e17ddc commit afec10b
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 13 deletions.
17 changes: 13 additions & 4 deletions multiply_add.sus
Original file line number Diff line number Diff line change
Expand Up @@ -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]];
}


Expand Down Expand Up @@ -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]);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/flattening.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ pub enum ConnectionWritePathElement {
ArrayIdx(SpanFlatID),
//StructField(FieldID)
}
#[derive(Debug)]
pub enum ConnectionWritePathElementComputed {
ArrayIdx(usize)
}

// These are assignable connections
#[derive(Debug)]
Expand Down
43 changes: 35 additions & 8 deletions src/instantiation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<SubModuleOrWire, FlatIDMarker>,
wires : FlatAlloc<RealWire, WireIDMarker>,
Expand Down Expand Up @@ -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<Vec<ConnectionWritePathElementComputed>> {
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::<usize>(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!(),
Expand All @@ -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);
}
};

Expand All @@ -255,11 +282,11 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> {
None
}
}
fn compute_compile_time(&self, wire_inst : &WireSource) -> Option<Value> {
fn compute_compile_time(&self, wire_inst : &WireSource, typ : &ConcreteType) -> Option<Value> {
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)?;
Expand Down Expand Up @@ -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 {
Expand Down
21 changes: 20 additions & 1 deletion src/typing.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -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())
}
}
}
}

0 comments on commit afec10b

Please sign in to comment.