Skip to content

Commit

Permalink
Extract some shared functionality between SV and VHDL
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Dec 6, 2024
1 parent 87b4747 commit 3fe5e73
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 84 deletions.
16 changes: 3 additions & 13 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod system_verilog;
pub mod vhdl;
mod shared;

pub use system_verilog::VerilogCodegenBackend;
pub use vhdl::VHDLCodegenBackend;
Expand All @@ -12,7 +13,7 @@ pub trait CodeGenBackend {
fn file_extension(&self) -> &str;
fn output_dir_name(&self) -> &str;
fn comment(&self) -> &str;
fn codegen(&self, md: &Module, instance: &InstantiatedModule) -> String;
fn codegen(&self, md: &Module, instance: &InstantiatedModule, use_latency: bool) -> String;

fn make_output_file(&self, name: &str) -> File {
let mut path = PathBuf::with_capacity(name.len() + self.output_dir_name().len() + self.file_extension().len() + 2);
Expand Down Expand Up @@ -40,7 +41,7 @@ pub trait CodeGenBackend {
return; // Continue
}
println!("Instantiating success: {inst_name}");
let code = self.codegen(md, &inst);
let code = self.codegen(md, &inst, true); // hardcode use_latency = true for now. Maybe forever, we'll see
write!(out_file, "{} {inst_name}\n{code}", self.comment()).unwrap();
}

Expand Down Expand Up @@ -88,14 +89,3 @@ pub trait CodeGenBackend {
}
}
}

fn mangle(str: &str) -> String {
let mut result = String::with_capacity(str.len());
for c in str.chars() {
if c.is_whitespace() || c == ':' {
continue;
}
result.push(if c.is_alphanumeric() { c } else { '_' });
}
result
}
45 changes: 45 additions & 0 deletions src/codegen/shared.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! Shared utilities
use std::borrow::Cow;

use crate::{instantiation::RealWire, linker::get_builtin_type, TypeUUID};


pub fn mangle(str: &str) -> String {
let mut result = String::with_capacity(str.len());
for c in str.chars() {
if c.is_whitespace() || c == ':' {
continue;
}
result.push(if c.is_alphanumeric() { c } else { '_' });
}
result
}

pub fn get_type_name_size(id: TypeUUID) -> u64 {
if id == get_builtin_type("int") {
32 // TODO concrete int sizes
} else if id == get_builtin_type("bool") {
1
} else {
println!("TODO Named Structs Size");
1 // todo!() // Named structs are not implemented yet
}
}

pub fn wire_name_with_latency(wire: &RealWire, absolute_latency: i64, use_latency: bool) -> Cow<str> {
assert!(wire.absolute_latency <= absolute_latency);
if use_latency && (wire.absolute_latency != absolute_latency) {
if absolute_latency < 0 {
Cow::Owned(format!("_{}_N{}", wire.name, -absolute_latency))
} else {
Cow::Owned(format!("_{}_D{}", wire.name, absolute_latency))
}
} else {
Cow::Borrowed(&wire.name)
}
}

pub fn wire_name_self_latency(wire: &RealWire, use_latency: bool) -> Cow<str> {
wire_name_with_latency(wire, wire.absolute_latency, use_latency)
}
37 changes: 4 additions & 33 deletions src/codegen/system_verilog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use crate::flattening::{DeclarationPortInfo, Instruction, Module, Port};
use crate::instantiation::{
InstantiatedModule, RealWire, RealWireDataSource, RealWirePathElem, CALCULATE_LATENCY_LATER,
};
use crate::{linker::get_builtin_type, typing::concrete_type::ConcreteType, value::Value};
use crate::{typing::concrete_type::ConcreteType, value::Value};

use super::mangle;
use super::shared::*;

#[derive(Debug)]
pub struct VerilogCodegenBackend;
Expand All @@ -25,19 +25,8 @@ impl super::CodeGenBackend for VerilogCodegenBackend {
fn comment(&self) -> &str {
"//"
}
fn codegen(&self, md: &Module, instance: &InstantiatedModule) -> String {
gen_verilog_code(md, instance, true)
}
}

fn get_type_name_size(id: TypeUUID) -> u64 {
if id == get_builtin_type("int") {
32 // TODO concrete int sizes
} else if id == get_builtin_type("bool") {
1
} else {
println!("TODO Named Structs Size");
1 // todo!() // Named structs are not implemented yet
fn codegen(&self, md: &Module, instance: &InstantiatedModule, use_latency: bool) -> String {
gen_verilog_code(md, instance, use_latency)
}
}

Expand Down Expand Up @@ -67,24 +56,6 @@ fn typ_to_declaration(mut typ: &ConcreteType, var_name: &str) -> String {
}
}

fn wire_name_with_latency(wire: &RealWire, absolute_latency: i64, use_latency: bool) -> Cow<str> {
assert!(wire.absolute_latency <= absolute_latency);

if use_latency && (wire.absolute_latency != absolute_latency) {
if absolute_latency < 0 {
Cow::Owned(format!("_{}_N{}", wire.name, -absolute_latency))
} else {
Cow::Owned(format!("_{}_D{}", wire.name, absolute_latency))
}
} else {
Cow::Borrowed(&wire.name)
}
}

fn wire_name_self_latency(wire: &RealWire, use_latency: bool) -> Cow<str> {
wire_name_with_latency(wire, wire.absolute_latency, use_latency)
}

struct CodeGenerationContext<'g, 'out, Stream: std::fmt::Write> {
md: &'g Module,
instance: &'g InstantiatedModule,
Expand Down
50 changes: 12 additions & 38 deletions src/codegen/vhdl.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use super::mangle;

use crate::{
flattening::{DeclarationPortInfo, Instruction},
instantiation::RealWire,
linker::{get_builtin_type, IsExtern},
linker::IsExtern,
typing::concrete_type::ConcreteType,
FlatAlloc, InstantiatedModule, Module, TypeUUID, WireIDMarker,
FlatAlloc, InstantiatedModule, Module, WireIDMarker,
};
use std::ops::Deref;
use std::{borrow::Cow, fmt::Write};
use std::fmt::Write;

use super::shared::*;

#[derive(Debug)]
pub struct VHDLCodegenBackend;
Expand All @@ -22,47 +23,19 @@ impl super::CodeGenBackend for VHDLCodegenBackend {
fn comment(&self) -> &str {
"--"
}
fn codegen(&self, md: &Module, instance: &InstantiatedModule) -> String {
gen_vhdl_code(md, instance)
}
}

fn wire_name_with_latency(wire: &RealWire, absolute_latency: i64) -> Cow<str> {
assert!(wire.absolute_latency <= absolute_latency);

if wire.absolute_latency != absolute_latency {
if absolute_latency < 0 {
Cow::Owned(format!("_{}_N{}", wire.name, -absolute_latency))
} else {
Cow::Owned(format!("_{}_D{}", wire.name, absolute_latency))
}
} else {
Cow::Borrowed(&wire.name)
fn codegen(&self, md: &Module, instance: &InstantiatedModule, use_latency: bool) -> String {
gen_vhdl_code(md, instance, use_latency)
}
}

fn wire_name_self_latency(wire: &RealWire) -> Cow<str> {
wire_name_with_latency(wire, wire.absolute_latency)
}

struct CodeGenerationContext<'g, 'out, Stream: std::fmt::Write> {
md: &'g Module,
instance: &'g InstantiatedModule,
program_text: &'out mut Stream,
use_latency: bool,
needed_untils: FlatAlloc<i64, WireIDMarker>,
}

fn get_type_name_size(id: TypeUUID) -> u64 {
if id == get_builtin_type("int") {
32 // TODO concrete int sizes
} else if id == get_builtin_type("bool") {
1
} else {
println!("TODO Named Structs Size");
1 // todo!() // Named structs are not implemented yet
}
}

fn typ_to_declaration(mut typ: &ConcreteType) -> String {
let mut array_string = String::new();
while let ConcreteType::Array(arr) = typ {
Expand Down Expand Up @@ -174,7 +147,7 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
return true;
})
.map(|(_, wire)| {
let signal_name = wire_name_self_latency(wire);
let signal_name = wire_name_self_latency(wire, self.use_latency);
let signal_type = typ_to_declaration(&wire.typ);
format!(" signal {signal_name} : {signal_type}")
})
Expand All @@ -191,13 +164,14 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
}
}

fn gen_vhdl_code(md: &Module, instance: &InstantiatedModule) -> String {
fn gen_vhdl_code(md: &Module, instance: &InstantiatedModule, use_latency: bool) -> String {
todo!("VHDl codegen is unfinshed");
let mut program_text = String::new();

let mut ctx = CodeGenerationContext {
md,
instance,
use_latency,
program_text: &mut program_text,
needed_untils: instance.compute_needed_untils(),
};
Expand Down

0 comments on commit 3fe5e73

Please sign in to comment.