Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

28 ranged int #38

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
104 changes: 66 additions & 38 deletions src/codegen_fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn typ_to_declaration(mut typ: &ConcreteType, var_name: &str) -> String {
}
match typ {
ConcreteType::Named(id) => {
let sz = get_type_name_size(*id);
let sz = get_type_name_size((*id).id);
VonTum marked this conversation as resolved.
Show resolved Hide resolved
if sz == 1 {
format!("{array_string} {var_name}")
} else {
Expand Down Expand Up @@ -83,7 +83,7 @@ struct CodeGenerationContext<'g, 'out, Stream: std::fmt::Write> {

use_latency: bool,

needed_untils : FlatAlloc<i64, WireIDMarker>
needed_untils: FlatAlloc<i64, WireIDMarker>,
}

impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream> {
Expand Down Expand Up @@ -128,7 +128,11 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
result
}

fn add_latency_registers(&mut self, wire_id: WireID, w: &RealWire) -> Result<(), std::fmt::Error> {
fn add_latency_registers(
&mut self,
wire_id: WireID,
w: &RealWire,
) -> Result<(), std::fmt::Error> {
if self.use_latency {
// Can do 0 iterations, when w.needed_until == w.absolute_latency. Meaning it's only needed this cycle
assert!(w.absolute_latency != CALCULATE_LATENCY_LATER);
Expand Down Expand Up @@ -170,10 +174,15 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
}
}

fn write_module_signature(&mut self, commented_out : bool) {
fn write_module_signature(&mut self, commented_out: bool) {
let comment_text = if commented_out { "// " } else { "" };
// First output the interface of the module
write!(self.program_text, "{comment_text}module {}(\n{comment_text}\tinput clk", mangle(&self.instance.name)).unwrap();
write!(
self.program_text,
"{comment_text}module {}(\n{comment_text}\tinput clk",
mangle(&self.instance.name)
)
.unwrap();
for (_id, port) in self.instance.interface_ports.iter_valids() {
let port_wire = &self.instance.wires[port.wire];
let input_or_output = if port.is_input { "input" } else { "output" };
Expand All @@ -183,7 +192,8 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
write!(
self.program_text,
",\n{comment_text}\t{input_or_output} {wire_doc} {wire_decl}"
).unwrap();
)
.unwrap();
}
write!(self.program_text, "\n{comment_text});\n\n").unwrap();

Expand All @@ -196,7 +206,7 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
}

/// Pass a `to` parameter to say to what the constant should be assigned.
fn write_constant(&mut self, to : &str, value : &Value) {
fn write_constant(&mut self, to: &str, value: &Value) {
match value {
Value::Bool(_) | Value::Integer(_) | Value::Unset => {
let v_str = value.inline_constant_to_string();
Expand All @@ -218,7 +228,7 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
if self.can_inline(w) {
continue;
}

if let Instruction::Declaration(wire_decl) =
&self.md.link_info.instructions[w.original_instruction]
{
Expand All @@ -228,11 +238,11 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
}
}
let wire_or_reg = w.source.wire_or_reg();

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

match &w.source {
RealWireDataSource::Select { root, path } => {
let wire_name = self.wire_name(*root, w.absolute_latency);
Expand All @@ -245,7 +255,8 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
" = {}{};",
op.op_text(),
self.wire_name(*right, w.absolute_latency)
).unwrap();
)
.unwrap();
}
RealWireDataSource::BinaryOp { op, left, right } => {
writeln!(
Expand All @@ -254,7 +265,8 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
self.wire_name(*left, w.absolute_latency),
op.op_text(),
self.wire_name(*right, w.absolute_latency)
).unwrap();
)
.unwrap();
}
RealWireDataSource::Constant { value } => {
// Trivial constants (bools & ints) should have been inlined already
Expand Down Expand Up @@ -323,17 +335,21 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
self.write_constant(&tabbed_name, &invalid_val);
"="
};

for s in sources {
let path = self.wire_ref_path_to_string(&s.to_path, w.absolute_latency);
let from_name = self.wire_name(s.from.from, w.absolute_latency);
self.program_text.write_char('\t').unwrap();
for cond in s.from.condition.iter() {
let cond_name = self.wire_name(cond.condition_wire, w.absolute_latency);
let invert = if cond.inverse {"!"} else {""};
let invert = if cond.inverse { "!" } else { "" };
write!(self.program_text, "if({invert}{cond_name}) ").unwrap();
}
writeln!(self.program_text, "{output_name}{path} {arrow_str} {from_name};").unwrap();
writeln!(
self.program_text,
"{output_name}{path} {arrow_str} {from_name};"
)
.unwrap();
}
writeln!(self.program_text, "end").unwrap();
}
Expand All @@ -349,35 +365,53 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
}
}
}
/// TODO probably best to have some smarter system for this in the future.

/// TODO probably best to have some smarter system for this in the future.
fn write_builtins(&mut self) {
match self.md.link_info.name.as_str() {
"LatencyOffset" => {
let _in_port = self.md.unwrap_port(PortID::from_hidden_value(0), true, "in");
let _out_port = self.md.unwrap_port(PortID::from_hidden_value(1), false, "out");
let _in_port = self
.md
.unwrap_port(PortID::from_hidden_value(0), true, "in");
let _out_port = self
.md
.unwrap_port(PortID::from_hidden_value(1), false, "out");
self.program_text.write_str("\tassign out = in;\n").unwrap();
}
"CrossDomain" => {
let _in_port = self.md.unwrap_port(PortID::from_hidden_value(0), true, "in");
let _out_port = self.md.unwrap_port(PortID::from_hidden_value(1), false, "out");
let _in_port = self
.md
.unwrap_port(PortID::from_hidden_value(0), true, "in");
let _out_port = self
.md
.unwrap_port(PortID::from_hidden_value(1), false, "out");
self.program_text.write_str("\tassign out = in;\n").unwrap();
}
"IntToBits" => {
let _value_port = self.md.unwrap_port(PortID::from_hidden_value(0), true, "value");
let _bits_port = self.md.unwrap_port(PortID::from_hidden_value(1), false, "bits");
let _value_port = self
.md
.unwrap_port(PortID::from_hidden_value(0), true, "value");
let _bits_port = self
.md
.unwrap_port(PortID::from_hidden_value(1), false, "bits");
for i in 0..32 {
write!(self.program_text, "\tassign bits[{i}] = value[{i}];\n").unwrap();
}
}
"BitsToInt" => {
let _bits_port = self.md.unwrap_port(PortID::from_hidden_value(0), true, "bits");
let _value_port = self.md.unwrap_port(PortID::from_hidden_value(1), false, "value");
let _bits_port = self
.md
.unwrap_port(PortID::from_hidden_value(0), true, "bits");
let _value_port = self
.md
.unwrap_port(PortID::from_hidden_value(1), false, "value");
for i in 0..32 {
write!(self.program_text, "\tassign value[{i}] = bits[{i}];\n").unwrap();
}
}
other => panic!("Unknown Builtin: \"{other}\"! Do not mark modules as __builtin__ yourself!")
other => {
panic!("Unknown Builtin: \"{other}\"! Do not mark modules as __builtin__ yourself!")
}
}
}

Expand All @@ -389,30 +423,24 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream>
impl Value {
fn inline_constant_to_string(&self) -> Cow<str> {
match self {
Value::Bool(b) => {
Cow::Borrowed(if *b { "1'b1" } else { "1'b0" })
}
Value::Integer(v) => {
Cow::Owned(format!("{v}"))
}
Value::Unset => {
Cow::Borrowed("'x")
}
Value::Bool(b) => Cow::Borrowed(if *b { "1'b1" } else { "1'b0" }),
Value::Integer(v) => Cow::Owned(format!("{v}")),
Value::Unset => Cow::Borrowed("'x"),
Value::Array(_) => unreachable!("Not an inline constant!"),
Value::Error => unreachable!("Error values should never have reached codegen!"),
}
}
}

impl Module {
fn unwrap_port(&self, port_id : PortID, is_input : bool, name : &str) -> &Port {
fn unwrap_port(&self, port_id: PortID, is_input: bool, name: &str) -> &Port {
let result = &self.ports[port_id];

assert_eq!(result.name, name);
assert_eq!(result.is_input, is_input);

result
}
}
}

impl RealWireDataSource {
Expand All @@ -439,7 +467,7 @@ pub fn gen_verilog_code(md: &Module, instance: &InstantiatedModule, use_latency:
instance,
program_text: &mut program_text,
use_latency,
needed_untils: instance.compute_needed_untils()
needed_untils: instance.compute_needed_untils(),
};
ctx.write_verilog_code();

Expand Down
Loading
Loading