Skip to content

Commit

Permalink
Separate domains from interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Jul 4, 2024
1 parent c28f087 commit 26cea14
Show file tree
Hide file tree
Showing 21 changed files with 360 additions and 327 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ One big decision all of these (including SUS) make is going all-in on Synchronou
## Main Features through examples
### Pipelining through [Latency Counting](philosophy/latency.md)
```Verilog
module pow17 : int i -> int o {
module pow17 {
interface pow17 : int i -> int o
int i2 = i * i
reg int i4 = i2 * i2
int i8 = i4 * i4
Expand All @@ -76,7 +77,8 @@ module pow17 : int i -> int o {

### FIZZ-BUZZ Lookup Table using Generative Code
```Verilog
module fizz_buzz_gen : int v -> int fb {
module fizz_buzz_gen {
interface fizz_buzz_gen : int v -> int fb
gen int FIZZ = 15
gen int BUZZ = 11
gen int FIZZ_BUZZ = 1511
Expand Down
15 changes: 10 additions & 5 deletions philosophy/control_flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ In practice, the biggest difference between these variants is that the code with

#### Example
```verilog
module m : int a, bool b -> int c {
module m {
interface m : int a, bool b -> int c
if a == 5 {
c = 4
} else if b {
Expand Down Expand Up @@ -96,7 +97,8 @@ The `for` statement only comes in its generative form. It's used to generate rep

#### Example
```verilog
module add_stuff_to_indices : int[10] values -> int[10] added_values {
module add_stuff_to_indices {
interface add_stuff_to_indices : int[10] values -> int[10] added_values
int[5] arr
for int i in 0..10 {
int t = values[i]
Expand All @@ -121,7 +123,8 @@ It comes in two variants: standalone `first` and `if first`.

#### Examples
```verilog
module first_enabled_bit : bool[10] values -> bool[10] is_first_bit {
module first_enabled_bit {
interface first_enabled_bit : bool[10] values -> bool[10] is_first_bit
chain bool found = false
for int i in 0..10 {
if values[i] {
Expand All @@ -143,7 +146,8 @@ module first_enabled_bit : bool[10] values -> bool[10] is_first_bit {
With `if first` we can merge both `else` blocks.

```verilog
module first_enabled_bit : bool[10] values -> bool[10] is_first_bit {
module first_enabled_bit {
interface first_enabled_bit : bool[10] values -> bool[10] is_first_bit
chain bool found = false
for int i in 0..10 {
if first values[i] in found {
Expand All @@ -160,7 +164,8 @@ module first_enabled_bit : bool[10] values -> bool[10] is_first_bit {
Often with uses of `first` one also wants to have a case where the condition never was valid.

```verilog
module first_enabled_bit_index : bool[10] values -> int first_bit, bool all_zero {
module first_enabled_bit_index {
interface first_enabled_bit_index : bool[10] values -> int first_bit, bool all_zero
chain bool found = false
for int i in 0..10 {
if first values[i] in found {
Expand Down
27 changes: 16 additions & 11 deletions philosophy/latency.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ Inserting latency registers on every path that requires them is an incredibly te
### Examples
#### Inference of latencies on ports
```Verilog
module example_md :
int[4] factors,
int add_to ->
int product,
int total {
module example_md {
interface example_md :
int[4] factors,
int add_to ->
int product,
int total
reg int mul0 = factors[0] * factors[1]
reg int mul1 = factors[2] * factors[3]
Expand All @@ -26,7 +27,8 @@ module example_md :

#### Automatic insertion of registers
```Verilog
module pow17 : int i -> int o {
module pow17 {
interface pow17 : int i -> int o
int i2 = i * i
reg int i4 = i2 * i2
int i8 = i4 * i4
Expand All @@ -38,8 +40,8 @@ module pow17 : int i -> int o {

#### Latency Specifiers
```Verilog
module module_taking_time :
int i'0 -> int o'5 {
module module_taking_time {
interface module_taking_time : int i'0 -> int o'5
o = i
}
```
Expand Down Expand Up @@ -102,7 +104,8 @@ We are given a directed graph of all wires and how they combinatorially depend o
Example:
```Verilog
// timeline is omitted here, not important
module Accumulator : int term, bool done -> int total_out {
module Accumulator {
interface Accumulator : int term, bool done -> int total_out
state int total
int new_total = total + term
Expand All @@ -127,7 +130,8 @@ On the edges are noted the minimum latency offsets in black. These are given. Th
Sadly, while it appears reasonable to think it's possible to assign a determinable latency. Observe this contrived example:

```Verilog
module NonDeterminableLatency : int a, int b -> int x, int y {
module NonDeterminableLatency {
interface NonDeterminableLatency : int a, int b -> int x, int y
reg int a_d = a
int t = a_d + b
reg reg reg int a_dd = a
Expand All @@ -151,7 +155,8 @@ To this problem I only really see three options:

Simply solve the above module by explicitly specifying latencies to the two inputs:
```Verilog
module LatencySpecified : int a'0, int b'1 -> int x, int y {
module LatencySpecified {
interface LatencySpecified : int a'0, int b'1 -> int x, int y
reg int a_d = a
int t = a_d + b
reg reg reg int a_dd = a
Expand Down
6 changes: 4 additions & 2 deletions philosophy/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ Generating the whole state machine is a combinatorial endeavour however, and a t
### Summing module
```Verilog
timeline (X, false -> /)* .. (X, true -> T)
module Accumulator : int term, bool done -> int total {
module Accumulator {
interface Accumulator : int term, bool done -> int total
state int tot := 0 // Initial value, not a real assignment
int new_tot = tot + term
Expand Down Expand Up @@ -69,7 +70,8 @@ The previous example was quite simple though, with the code's active state machi

```Verilog
timeline (X -> X) .. (/ -> X) .. (/ -> X) .. (/ -> X)
module Unpack4<T> : T[4] packed -> T out_stream {
module Unpack4<T> {
interface Unpack4 : T[4] packed -> T out_stream
state int st := 0 // Initial value, not a real assignment
state T[3] stored_packed
Expand Down
12 changes: 6 additions & 6 deletions src/abstract_type.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{cell::RefCell, ops::Deref};

use crate::{arena_alloc::FlatAlloc, errors::ErrorCollector, file_position::{Span, SpanFile}, flattening::{BinaryOperator, DomainID, DomainIDMarker, FlatID, Interface, UnaryOperator}, linker::{get_builtin_type, NamedType, Resolver, TypeUUID, TypeUUIDMarker}, template::{TemplateID, TemplateIDMarker, TemplateInputs}, to_string::map_to_type_names};
use crate::{arena_alloc::FlatAlloc, errors::ErrorCollector, file_position::{Span, SpanFile}, flattening::{BinaryOperator, DomainID, DomainIDMarker, FlatID, UnaryOperator}, linker::{get_builtin_type, NamedType, Resolver, TypeUUID, TypeUUIDMarker}, template::{TemplateID, TemplateIDMarker, TemplateInputs}, to_string::map_to_type_names};

/// This contains only the information that can be easily type-checked.
///
Expand Down Expand Up @@ -86,15 +86,15 @@ enum DomainTypeSubstitution {
}

pub enum BestName {
ExistingInterface,
NamedDomain,
SubModule(FlatID, DomainID),
NamedWire(FlatID),
UnnamedWire
}
impl BestName {
fn strength(&self) -> i8 {
match self {
BestName::ExistingInterface => 3,
BestName::NamedDomain => 3,
BestName::SubModule(_, _) => 2,
BestName::NamedWire(_) => 1,
BestName::UnnamedWire => 0
Expand All @@ -116,9 +116,9 @@ pub struct TypeUnifier<'linker, 'errs> {
}

impl<'linker, 'errs> TypeUnifier<'linker, 'errs> {
pub fn new(linker_types : Resolver<'linker, 'errs, TypeUUIDMarker, NamedType>, template_inputs : &TemplateInputs, errors : &'errs ErrorCollector<'linker>, interfaces : &FlatAlloc<Interface, DomainIDMarker>) -> Self {
let domains = interfaces.iter().map(|(_id, interface)| DomainTypeSubstitution::KnownDomain { name: interface.name.clone() }).collect();
let final_domains = interfaces.iter().map(|(_id, _interface)| BestName::ExistingInterface).collect();
pub fn new(linker_types : Resolver<'linker, 'errs, TypeUUIDMarker, NamedType>, template_inputs : &TemplateInputs, errors : &'errs ErrorCollector<'linker>, domain_names : &FlatAlloc<String, DomainIDMarker>) -> Self {
let domains = domain_names.iter().map(|(_id, name)| DomainTypeSubstitution::KnownDomain { name: name.clone() }).collect();
let final_domains = domain_names.iter().map(|(_id, _interface)| BestName::NamedDomain).collect();
Self {
linker_types,
template_type_names : map_to_type_names(template_inputs),
Expand Down
4 changes: 4 additions & 0 deletions src/arena_alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,10 @@ impl<T, IndexMarker : UUIDMarker> FlatAlloc<T, IndexMarker> {
let uuid = self.data.len();
UUID(uuid, PhantomData)
}
pub fn last_id(&self) -> UUID<IndexMarker> {
assert!(self.data.len() >= 1, "Can't get last_id on empty FlatAlloc");
UUID(self.data.len() - 1, PhantomData)
}
pub fn alloc(&mut self, value : T) -> UUID<IndexMarker> {
let uuid = self.data.len();
self.data.push(value);
Expand Down
2 changes: 1 addition & 1 deletion src/compiler_top.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn update_file(text : String, file_id : FileUUID, linker : &mut Linker) {
pub fn recompile_all(linker : &mut Linker) {
// First reset all modules back to post-gather_initial_file_data
for (_, md) in &mut linker.modules {
let Module { link_info, ports:_, main_interface_used:_, interfaces:_, domains:_, instructions, instantiations } = md;
let Module { link_info, instructions, instantiations, .. } = md;
link_info.reset_to(link_info.after_initial_parse_cp);
link_info.after_flatten_cp = None;
instructions.clear();
Expand Down
8 changes: 4 additions & 4 deletions src/dev_aid/lsp/hover_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec<M
let mut details_vec : Vec<&str> = Vec::with_capacity(5);
let domain_str = if md.is_multi_domain() {
if let DomainType::Physical(ph) = decl.typ.domain {
Some(DomainType::physical_to_string(ph, &md.interfaces))
Some(DomainType::physical_to_string(ph, &md.domains))
} else {None}
} else {None};

Expand Down Expand Up @@ -122,7 +122,7 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec<M
DomainType::Generative => {details_vec.push(Cow::Borrowed("gen"))}
DomainType::Physical(ph) => {
if md.is_multi_domain() {
details_vec.push(Cow::Owned(DomainType::physical_to_string(ph, &md.interfaces)))
details_vec.push(Cow::Owned(DomainType::physical_to_string(ph, &md.domains)))
}
}
};
Expand Down Expand Up @@ -168,8 +168,8 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec<M
LocationInfo::Port(_sm, md, port_id) => {
hover.sus_code(md.make_port_info_string(port_id, &linker.files[md.link_info.file].file_text));
}
LocationInfo::Interface(_md_uuid, md, interface_id, _) => {
hover.sus_code(md.make_interface_info_string(interface_id, &linker.files[md.link_info.file].file_text));
LocationInfo::Interface(_md_uuid, md, _, interface) => {
hover.sus_code(md.make_interface_info_string(interface, &linker.files[md.link_info.file].file_text));
}
};

Expand Down
25 changes: 12 additions & 13 deletions src/dev_aid/lsp/semantic_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const TOKEN_TYPES : [SemanticTokenType; 8] = [

fn get_semantic_token_type_from_ide_token(tok : IDEIdentifierType) -> u32 {
match tok {
IDEIdentifierType::Local { is_state : _, interface } => interface % NUM_INTERFACE_DISTINGUISHERS,
IDEIdentifierType::Local { is_state : _, domain: interface } => interface % NUM_INTERFACE_DISTINGUISHERS,
IDEIdentifierType::Generative => NUM_INTERFACE_DISTINGUISHERS, // ENUM_MEMBER
IDEIdentifierType::Constant => NUM_INTERFACE_DISTINGUISHERS, // ENUM_MEMBER
IDEIdentifierType::Interface => NUM_INTERFACE_DISTINGUISHERS+1, // FUNCTION
Expand All @@ -36,7 +36,7 @@ const TOKEN_MODIFIERS : [SemanticTokenModifier; 2] = [
// Produces a bitset with 'modifier bits'
fn get_modifiers_for_token(tok : IDEIdentifierType) -> u32 {
match tok {
IDEIdentifierType::Local { is_state: true, interface:_ } => 1, // ASYNC
IDEIdentifierType::Local { is_state: true, domain:_ } => 1, // ASYNC
IDEIdentifierType::Generative => 2, // MODIFICATION
_other => 0
}
Expand Down Expand Up @@ -94,22 +94,21 @@ fn convert_to_semantic_tokens(file_data : &FileData, ide_tokens : &mut[(Span, ID

#[derive(Debug,Clone,Copy,PartialEq,Eq)]
enum IDEIdentifierType {
Local{is_state : bool, interface : u32},
Local{is_state : bool, domain : u32},
Generative,
Type,
Interface,
Constant
}

impl IDEIdentifierType {
fn make_local(is_state : bool, domain : DomainID, main_interface_used : bool) -> IDEIdentifierType {
let offset = if main_interface_used {0} else {1};
IDEIdentifierType::Local { is_state, interface: (domain.get_hidden_value() - offset) as u32 }
fn make_local(is_state : bool, domain : DomainID) -> IDEIdentifierType {
IDEIdentifierType::Local { is_state, domain: domain.get_hidden_value() as u32 }
}
fn from_identifier_typ(t : IdentifierType, domain : DomainType, main_interface_used : bool) -> IDEIdentifierType {
fn from_identifier_typ(t : IdentifierType, domain : DomainType) -> IDEIdentifierType {
match t {
IdentifierType::Local => Self::make_local(false, domain.unwrap_physical(), main_interface_used),
IdentifierType::State => Self::make_local(true, domain.unwrap_physical(), main_interface_used),
IdentifierType::Local => Self::make_local(false, domain.unwrap_physical()),
IdentifierType::State => Self::make_local(true, domain.unwrap_physical()),
IdentifierType::Generative => IDEIdentifierType::Generative
}
}
Expand All @@ -120,8 +119,8 @@ fn walk_name_color(file : &FileData, linker : &Linker) -> Vec<(Span, IDEIdentifi

tree_walk::visit_all(linker, file, |span, item| {
result.push((span, match item {
LocationInfo::InModule(_md_id, md, _, InModule::NamedLocal(decl)) => {
IDEIdentifierType::from_identifier_typ(decl.identifier_type, decl.typ.domain, md.main_interface_used)
LocationInfo::InModule(_md_id, _md, _, InModule::NamedLocal(decl)) => {
IDEIdentifierType::from_identifier_typ(decl.identifier_type, decl.typ.domain)
}
LocationInfo::InModule(_md_id, _, _, InModule::NamedSubmodule(_)) => {
IDEIdentifierType::Interface
Expand All @@ -142,8 +141,8 @@ fn walk_name_color(file : &FileData, linker : &Linker) -> Vec<(Span, IDEIdentifi
}
}
LocationInfo::Port(_, md, port_id) => {
let interface = md.ports[port_id].interface;
IDEIdentifierType::make_local(false, interface, md.main_interface_used)
let interface = md.ports[port_id].domain;
IDEIdentifierType::make_local(false, interface)
}
LocationInfo::Interface(_, _, _, _) => {
IDEIdentifierType::Interface
Expand Down
11 changes: 4 additions & 7 deletions src/dev_aid/lsp/tree_walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use std::ops::Deref;

use crate::{
file_position::Span, flattening::{Declaration, DeclarationPortInfo, DomainID, FlatID, Instruction, Interface, Module, ModuleInterfaceReference, PortID, SubModuleInstance, WireInstance, WireReference, WireReferenceRoot, WireSource, WrittenType}, linker::{FileData, FileUUID, LinkInfo, Linker, ModuleUUID, NameElem}, template::{GenerativeTemplateInputKind, GlobalReference, TemplateArgKind, TemplateID, TemplateInput, TemplateInputKind, TypeTemplateInputKind}
file_position::Span, flattening::{Declaration, DeclarationPortInfo, FlatID, Instruction, Interface, InterfaceID, Module, ModuleInterfaceReference, PortID, SubModuleInstance, WireInstance, WireReference, WireReferenceRoot, WireSource, WrittenType}, linker::{FileData, FileUUID, LinkInfo, Linker, ModuleUUID, NameElem}, template::{GenerativeTemplateInputKind, GlobalReference, TemplateArgKind, TemplateID, TemplateInput, TemplateInputKind, TypeTemplateInputKind}
};

#[derive(Clone, Copy, Debug)]
Expand All @@ -21,7 +21,7 @@ pub enum LocationInfo<'linker> {
/// The contained module only refers to the module on which the port is defined
/// No reference to the module in which the reference was found is provided
Port(&'linker SubModuleInstance, &'linker Module, PortID),
Interface(ModuleUUID, &'linker Module, DomainID, &'linker Interface)
Interface(ModuleUUID, &'linker Module, InterfaceID, &'linker Interface)
}

/// Permits really efficient [RefersTo::refers_to_same_as] [LocationInfo] checking
Expand All @@ -30,7 +30,7 @@ pub struct RefersTo {
pub local : Option<(ModuleUUID, FlatID)>,
pub global : Option<NameElem>,
pub port : Option<(ModuleUUID, PortID)>,
pub interface : Option<(ModuleUUID, DomainID)>,
pub interface : Option<(ModuleUUID, InterfaceID)>,
pub template_input : Option<(NameElem, TemplateID)>
}

Expand Down Expand Up @@ -258,10 +258,7 @@ impl<'linker, Visitor : FnMut(Span, LocationInfo<'linker>), Pruner : Fn(Span) ->
}
}

let mut interface_iter = md.interfaces.iter();
// Skip main interface
interface_iter.next();
for (interface_id, interface) in interface_iter {
for (interface_id, interface) in &md.interfaces {
self.visit(interface.name_span, LocationInfo::Interface(md_id, md, interface_id, interface));
}

Expand Down
Loading

0 comments on commit 26cea14

Please sign in to comment.