kaze/verilog/
ir.rs

1use crate::code_writer;
2use crate::graph;
3
4use std::io::{Result, Write};
5
6pub struct NodeDecl {
7    pub net_type: NetType,
8    pub name: String,
9    pub bit_width: u32,
10}
11
12impl NodeDecl {
13    pub fn write<W: Write>(&self, w: &mut code_writer::CodeWriter<W>) -> Result<()> {
14        w.append_indent()?;
15        self.net_type.write(w)?;
16        w.append(" ")?;
17        if self.bit_width > 1 {
18            w.append(&format!("[{}:{}] ", self.bit_width - 1, 0))?;
19        }
20        w.append(&format!("{};", self.name))?;
21        w.append_newline()?;
22
23        Ok(())
24    }
25}
26
27pub enum NetType {
28    Reg,
29    Wire,
30}
31
32impl NetType {
33    pub fn write<W: Write>(&self, w: &mut code_writer::CodeWriter<W>) -> Result<()> {
34        w.append(match self {
35            NetType::Reg => "reg",
36            NetType::Wire => "wire",
37        })
38    }
39}
40
41pub struct AssignmentContext {
42    assignments: Vec<Assignment>,
43    local_decls: Vec<NodeDecl>,
44}
45
46impl AssignmentContext {
47    pub fn new() -> AssignmentContext {
48        AssignmentContext {
49            assignments: Vec::new(),
50            local_decls: Vec::new(),
51        }
52    }
53
54    pub fn gen_temp(&mut self, expr: Expr, bit_width: u32) -> Expr {
55        let name = format!("__temp_{}", self.local_decls.len());
56
57        self.local_decls.push(NodeDecl {
58            net_type: NetType::Wire,
59            name: name.clone(),
60            bit_width,
61        });
62
63        self.assignments.push(Assignment {
64            target_name: name.clone(),
65            expr,
66        });
67
68        Expr::Ref { name }
69    }
70
71    pub fn is_empty(&self) -> bool {
72        self.assignments.is_empty()
73    }
74
75    pub fn push(&mut self, assignment: Assignment) {
76        self.assignments.push(assignment);
77    }
78
79    pub fn write<W: Write>(&self, w: &mut code_writer::CodeWriter<W>) -> Result<()> {
80        if !self.local_decls.is_empty() {
81            for node_decl in self.local_decls.iter() {
82                node_decl.write(w)?;
83            }
84            w.append_newline()?;
85        }
86
87        for assignment in self.assignments.iter() {
88            assignment.write(w)?;
89        }
90
91        Ok(())
92    }
93}
94
95pub struct Assignment {
96    pub target_name: String,
97    pub expr: Expr,
98}
99
100impl Assignment {
101    fn write<W: Write>(&self, w: &mut code_writer::CodeWriter<W>) -> Result<()> {
102        w.append_indent()?;
103        w.append(&format!("assign {}", self.target_name))?;
104        w.append(" = ")?;
105        self.expr.write(w)?;
106        w.append(";")?;
107        w.append_newline()?;
108
109        Ok(())
110    }
111}
112
113#[derive(Clone)]
114pub enum Expr {
115    BinOp {
116        lhs: Box<Expr>,
117        rhs: Box<Expr>,
118        op: BinOp,
119    },
120    Bits {
121        source: Box<Expr>,
122        range_high: u32,
123        range_low: u32,
124    },
125    Concat {
126        lhs: Box<Expr>,
127        rhs: Box<Expr>,
128    },
129    Constant {
130        bit_width: u32,
131        value: u128,
132    },
133    Ref {
134        name: String,
135    },
136    Repeat {
137        source: Box<Expr>,
138        count: u32,
139    },
140    Signed {
141        source: Box<Expr>,
142    },
143    Ternary {
144        cond: Box<Expr>,
145        when_true: Box<Expr>,
146        when_false: Box<Expr>,
147    },
148    UnOp {
149        source: Box<Expr>,
150        op: UnOp,
151    },
152}
153
154impl Expr {
155    pub fn from_constant(value: &graph::Constant, bit_width: u32) -> Expr {
156        Expr::Constant {
157            bit_width,
158            value: value.numeric_value(),
159        }
160    }
161
162    pub fn write<W: Write>(&self, w: &mut code_writer::CodeWriter<W>) -> Result<()> {
163        match self {
164            Expr::BinOp { lhs, rhs, op } => {
165                lhs.write(w)?;
166                w.append(&format!(
167                    " {} ",
168                    match op {
169                        BinOp::Add => "+",
170                        BinOp::BitAnd => "&",
171                        BinOp::BitOr => "|",
172                        BinOp::BitXor => "^",
173                        BinOp::Equal => "==",
174                        BinOp::NotEqual => "!=",
175                        BinOp::LessThan => "<",
176                        BinOp::LessThanEqual => "<=",
177                        BinOp::GreaterThan => ">",
178                        BinOp::GreaterThanEqual => ">=",
179                        BinOp::Shl => "<<",
180                        BinOp::Shr => ">>",
181                        BinOp::ShrArithmetic => ">>>",
182                        BinOp::Sub => "-",
183                        BinOp::Mul => "*",
184                    }
185                ))?;
186                rhs.write(w)?;
187            }
188            Expr::Bits {
189                source,
190                range_high,
191                range_low,
192            } => {
193                source.write(w)?;
194                if range_high != range_low {
195                    w.append(&format!("[{}:{}]", range_high, range_low))?;
196                } else {
197                    w.append(&format!("[{}]", range_high))?;
198                }
199            }
200            Expr::Concat { lhs, rhs } => {
201                w.append("{")?;
202                lhs.write(w)?;
203                w.append(", ")?;
204                rhs.write(w)?;
205                w.append("}")?;
206            }
207            Expr::Constant { bit_width, value } => {
208                w.append(&format!("{}'h{:x}", bit_width, value))?;
209            }
210            Expr::Ref { name } => {
211                w.append(name)?;
212            }
213            Expr::Repeat { source, count } => {
214                w.append(&format!("{{{}{{", count))?;
215                source.write(w)?;
216                w.append("}}")?;
217            }
218            Expr::Signed { source } => {
219                w.append("$signed(")?;
220                source.write(w)?;
221                w.append(")")?;
222            }
223            Expr::Ternary {
224                cond,
225                when_true,
226                when_false,
227            } => {
228                cond.write(w)?;
229                w.append(" ? ")?;
230                when_true.write(w)?;
231                w.append(" : ")?;
232                when_false.write(w)?;
233            }
234            Expr::UnOp { source, op } => {
235                w.append(match op {
236                    UnOp::Not => "~",
237                })?;
238                source.write(w)?;
239            }
240        }
241
242        Ok(())
243    }
244}
245
246#[derive(Clone)]
247pub enum BinOp {
248    Add,
249    BitAnd,
250    BitOr,
251    BitXor,
252    Equal,
253    NotEqual,
254    LessThan,
255    LessThanEqual,
256    GreaterThan,
257    GreaterThanEqual,
258    Shl,
259    Shr,
260    ShrArithmetic,
261    Sub,
262    Mul,
263}
264
265#[derive(Clone)]
266pub enum UnOp {
267    Not,
268}