Skip to content

Commit

Permalink
Switch to SystemVerilog for code generation
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Jul 11, 2024
1 parent 092d495 commit fda21b6
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 37 deletions.
58 changes: 27 additions & 31 deletions src/codegen_fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,21 @@ fn get_type_name_size(id: TypeUUID) -> u64 {

/// Creates the Verilog variable declaration for tbis variable.
///
/// IE for `int[15] myVar (reg)` it creates `reg[31:0] myVar[14:0]`
fn typ_to_verilog_array(typ: &ConcreteType, prefix : &str, var_name: &str) -> String {
/// IE for `int[15] myVar` it creates `logic[31:0] myVar[14:0]`
fn typ_to_verilog_array(typ: &ConcreteType, var_name: &str) -> String {
match typ {
ConcreteType::Named(id) => {
let sz = get_type_name_size(*id);
if sz == 1 {
format!("{prefix} {var_name}")
format!("logic {var_name}")
} else {
format!("{prefix}[{}:0] {var_name}", sz - 1)
format!("logic[{}:0] {var_name}", sz - 1)
}
}
ConcreteType::Array(arr) => {
let (content_typ, size) = arr.deref();
let sz = size.unwrap_value().unwrap_integer();
let mut result = typ_to_verilog_array(content_typ, prefix, var_name);
let mut result = typ_to_verilog_array(content_typ, var_name);
use std::fmt::Write;
write!(result, "[{}:0]", sz - 1).unwrap();
result
Expand Down Expand Up @@ -118,9 +118,9 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
let from = wire_name_with_latency(w, i, self.use_latency);
let to = wire_name_with_latency(w, i + 1, self.use_latency);

let var_decl = typ_to_verilog_array(&w.typ, "/*latency*/ reg", &to);
let var_decl = typ_to_verilog_array(&w.typ, &to);

writeln!(self.program_text, "{var_decl}; always @(posedge clk) begin {to} <= {from}; end")?;
writeln!(self.program_text, "/*latency*/ {var_decl}; always_ff @(posedge clk) begin {to} <= {from}; end")?;
}
}
Ok(())
Expand All @@ -135,13 +135,14 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
let input_or_output = if port.is_input {
"input"
} else {
"output /*mux_wire*/ reg"
"output"
};
let wire_doc = port_wire.source.get_sv_info_doc();
let wire_name = wire_name_self_latency(port_wire, self.use_latency);
let wire_decl = typ_to_verilog_array(&port_wire.typ, input_or_output, &wire_name);
let wire_decl = typ_to_verilog_array(&port_wire.typ, &wire_name);
writeln!(
self.program_text,
"\t{wire_decl},"
"\t{wire_doc}{input_or_output} {wire_decl},"
)?;
}
writeln!(self.program_text, ");\n")?;
Expand All @@ -161,31 +162,16 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
&self.md.instructions[w.original_instruction]
{
// Don't print named inputs and outputs, already did that in interface
if let DeclarationPortInfo::RegularPort {
is_input: _,
port_id: _,
} = wire_decl.is_port
if let DeclarationPortInfo::RegularPort {..} = wire_decl.is_port
{
continue;
}
}
let wire_or_reg = if let RealWireDataSource::Multiplexer {
is_state,
sources: _,
} = &w.source
{
if is_state.is_some() {
"reg"
} else {
"/*mux_wire*/ reg"
}
} else {
"wire"
};
let wire_or_reg = w.source.get_sv_info_doc();

let wire_name = wire_name_self_latency(w, self.use_latency);
let wire_decl = typ_to_verilog_array(&w.typ, wire_or_reg, &wire_name);
write!(self.program_text, "{wire_decl}")?;
let wire_decl = typ_to_verilog_array(&w.typ, &wire_name);
write!(self.program_text, "{wire_or_reg}{wire_decl}")?;

match &w.source {
RealWireDataSource::Select { root, path } => {
Expand Down Expand Up @@ -270,10 +256,10 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
if is_state.is_some() {
writeln!(
self.program_text,
"/*always_ff*/ always @(posedge clk) begin"
"always_ff @(posedge clk) begin"
)?;
} else {
writeln!(self.program_text, "/*always_comb*/ always @(*) begin")?;
writeln!(self.program_text, "always_comb begin")?;
writeln!(self.program_text, "\t{output_name} <= 1'bX; // Combinatorial wires are not defined when not valid")?;
}

Expand Down Expand Up @@ -310,6 +296,16 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
}
}

impl RealWireDataSource {
fn get_sv_info_doc(&self) -> &str {
match self {
RealWireDataSource::Multiplexer {is_state : Some(_), sources: _} => "/*state*/ ",
RealWireDataSource::Multiplexer {is_state : None, sources: _} => "/*mux_wire*/ ",
_ => "",
}
}
}

pub fn gen_verilog_code(md: &Module, instance: &InstantiatedModule, use_latency: bool) -> String {
let mut program_text = String::new();

Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ fn codegen_instance(inst: &InstantiatedModule, md: &Module, out_file: &mut File)

fn codegen_to_file(md: &Module) {
let module_name = md.link_info.name.deref();
let mut out_file = File::create(format!("verilog_output/{module_name}.v")).unwrap();
let mut out_file = File::create(format!("verilog_output/{module_name}.sv")).unwrap();
md.instantiations.for_each_instance(|_template_args, inst| {
codegen_instance(inst.as_ref(), md, &mut out_file)
});
}

fn codegen_with_dependencies(linker: &Linker, md: &Module, file_name: &str) {
let mut out_file = File::create(format!("verilog_output/{file_name}.v")).unwrap();
let mut out_file = File::create(format!("verilog_output/{file_name}.sv")).unwrap();

let mut top_level_instances: Vec<Rc<InstantiatedModule>> = Vec::new();
md.instantiations.for_each_instance(|_template_args, inst| {
Expand Down
8 changes: 4 additions & 4 deletions src/to_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,16 @@ impl Value {
Value::Bool(b) => if *b { "1'b1" } else { "1'b0" }.to_owned(),
Value::Integer(v) => v.to_string(),
Value::Array(arr_box) => {
let mut result = "[".to_owned();
let mut result = "'{".to_owned();
for v in arr_box.iter() {
result.push_str(&v.to_string());
result.push_str(", ");
}
result.push(']');
result.push('}');
result
}
Value::Unset => "Value::Unset".to_owned(),
Value::Error => "Value::Error".to_owned(),
Value::Unset => "1'bX/*UNSET*/".to_owned(),
Value::Error => "1'bX/*ERROR*/".to_owned(),
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions verilog_output/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
*.v
*.sv
*.vhdl
*.vh

0 comments on commit fda21b6

Please sign in to comment.