yarig/generator/
gen_sv.rs

1use crate::{
2    comp::hw_info::{CastInfo, ExprId, LogicExpr, PortDir, PortInfo, SignalDecl, SignalDef, SignalInfo, SignalKind},
3    rifgen::{EnumEntry, ResetDef}
4};
5
6use super::{
7    gen_common::{CompInfo, GeneratorBase, GeneratorBaseSetting, GeneratorCore},
8    trait_hw::GeneratorHw
9};
10
11use yarig_macro::add_gen_core;
12#[add_gen_core("sv")]
13pub struct GeneratorSv {
14    /// True when current module instance is a bridge
15    is_bridge : bool,
16}
17
18impl GeneratorSv {
19
20    pub fn new(setting: GeneratorBaseSetting) -> Self {
21        GeneratorSv {
22            core: GeneratorCore::new(0,setting),
23            is_bridge: false
24        }
25    }
26
27    fn add_signal_def(&mut self, def: &SignalDef, prefix: Option<&String> ) {
28        match &def.kind {
29            SignalKind::Unsigned(w) => {
30                self.write("logic ");
31                if *w > 1 {
32                    self.write(&format!("[{}:0] ", w-1));
33                }
34            },
35            SignalKind::Signed(w)   => self.write(&format!("logic signed [{}:0] ", w-1)),
36            SignalKind::Custom((Some(pkg),n)) => self.write(&format!("{pkg}::{n} ")),
37            SignalKind::Custom((None,n))      => self.write(&format!("{n} ")),
38            SignalKind::Integer     => self.write("int "),
39            SignalKind::Address     => self.write(&format!("logic [{}:0] ", self.addr_width()-1)),
40            SignalKind::Data        => self.write(&format!("logic [{}:0] ", self.data_width()-1)),
41        }
42        if let Some(prefix) = prefix {
43            if let Some(base_name) = def.name.strip_prefix("rif_") {
44                self.write(&format!("rif_{prefix}_{}", base_name.trim()));
45            } else {
46                self.write(&format!("{prefix}_{}",def.name.trim()));
47            }
48        } else {
49            self.write(def.name.trim());
50        }
51        if def.dim > 0 {
52            self.write(&format!("[{}]", def.dim));
53        }
54    }
55
56    fn write_signal_seq(&mut self, id: &ExprId, val: &LogicExpr, lvl: usize) {
57        self.write(&" ".repeat(3*lvl));
58        self.add_expr_id(id);
59        self.write(" <= ");
60        self.add_logic_expr(val, 0, false);
61        self.write(";\n");
62    }
63
64    fn add_logic_expr(&mut self, expr: &LogicExpr, lvl: usize, is_part: bool) {
65        self.core.write(&" ".repeat(3*lvl));
66        match expr {
67            LogicExpr::Id(expr_id) => self.add_expr_id(expr_id),
68            LogicExpr::Cast(cast_info, e) => {
69                let has_par = !cast_info.is_none();
70                match cast_info {
71                    CastInfo::None => {}
72                    CastInfo::Unsigned => self.core.write("$unsigned("),
73                    CastInfo::Signed => self.core.write("$signed("),
74                    CastInfo::Custom(pkg, name) => {
75                        if !pkg.is_empty() {
76                            self.core.write(pkg);
77                            self.core.write("::");
78                        }
79                        self.core.write(name);
80                        self.core.write("'(");
81                    }
82                }
83                self.add_logic_expr(e, 0, false);
84                if has_par {
85                    self.core.write(")");
86                }
87            }
88            LogicExpr::CastFrom(_,_, e) => self.add_logic_expr(e, lvl, is_part),
89            LogicExpr::ValueU(v, w) => {
90                let n = (w+3)>>2;
91                match w {
92                    1 => self.core.write(&format!("1'b{v}")),
93                    2..=12 => self.core.write(&format!("{w}'d{v}")),
94                    _ => self.core.write(&format!("{w}'h{v:0n$x}")),
95                }
96            }
97            LogicExpr::ValueI(v, w) => {
98                let n = (w+3)>>2;
99                match w {
100                    0..=12 => {
101                        if *v < 0 {
102                            self.core.write(&format!("-{w}'sd{}", v.abs()))
103                        } else {
104                            self.core.write(&format!("{w}'sd{v}"))
105                        }
106                    }
107                    _ => self.core.write(&format!("{w}'sh{v:0n$x}")),
108                }
109            }
110            LogicExpr::Not(e) => {
111                self.core.write("!");
112                self.add_logic_expr(e, 0, true);
113            }
114            LogicExpr::NotB(e) => {
115                self.core.write("~");
116                self.add_logic_expr(e, 0, true);
117            }
118            LogicExpr::Concat(exprs) => {
119                self.core.write("{");
120                let mut expr_iter = exprs.iter().peekable();
121                while let Some(e) = expr_iter.next() {
122                    self.add_logic_expr(e, 0, false);
123                    if expr_iter.peek().is_some() {
124                        self.core.write(",");
125                    }
126                }
127                self.core.write("}");
128            }
129            LogicExpr::Add(lhs, rhs)  => self.add_two_expr(lhs, rhs, " + " , false),
130            LogicExpr::Sub(lhs, rhs)  => self.add_two_expr(lhs, rhs, " - " , false),
131            LogicExpr::Eq(lhs, rhs)   => self.add_two_expr(lhs, rhs, " == ", false),
132            LogicExpr::Neq(lhs, rhs)  => self.add_two_expr(lhs, rhs, " != ", false),
133            LogicExpr::Gte(lhs, rhs)  => self.add_two_expr(lhs, rhs, " >= ", false),
134            LogicExpr::Lte(lhs, rhs)  => self.add_two_expr(lhs, rhs, " <= ", false),
135            LogicExpr::Lt(lhs, rhs)   => self.add_two_expr(lhs, rhs, " < " , false),
136            LogicExpr::Xor(lhs, rhs)  => self.add_two_expr(lhs, rhs, " ^ ", is_part),
137            LogicExpr::OrB(lhs, rhs)  => self.add_two_expr(lhs, rhs, " | ", is_part),
138            LogicExpr::AndB(lhs, rhs) => self.add_two_expr(lhs, rhs, " & ", is_part),
139            LogicExpr::Or(vec)  => self.add_n_expr(vec, " || ", is_part, lvl),
140            LogicExpr::And(vec) => self.add_n_expr(vec, " && ", is_part, lvl),
141            LogicExpr::Ite(it_exprs, else_expr) => {
142                let tab = if lvl>0 {format!("\n{}", " ".repeat(3*lvl))} else {" ".to_owned()};
143                if is_part {self.core.write("(");}
144                for it_expr in it_exprs {
145                    self.add_logic_expr(&it_expr.0, 0, false /*it_expr.0.nb() > 1*/);
146                    self.core.write(" ? ");
147                    self.add_logic_expr(&it_expr.1, 0, it_expr.1.nb() > 1 || it_expr.1.is_ite() );
148                    self.core.write(" :");
149                    self.core.write(&tab);
150                }
151                self.add_logic_expr(else_expr, 0, else_expr.nb() > 1);
152                if is_part {self.core.write(")");}
153            }
154        }
155    }
156
157    fn add_two_expr(&mut self, lhs: &LogicExpr, rhs: &LogicExpr, op: &str, is_part: bool) {
158        if is_part {self.write("(");}
159        self.add_logic_expr(lhs, 0, true);
160        self.write(op);
161        if rhs.is_ite() {
162            self.write("\n      ");
163        }
164        self.add_logic_expr(rhs, 0, true);
165        if is_part {self.write(")");}
166    }
167
168    fn add_n_expr(&mut self, exprs: &[LogicExpr], op: &str, is_part: bool, lvl: usize) {
169        let is_part = is_part && exprs.len() > 1;
170        let eol = if !is_part && lvl > 0 && exprs.len() > 2 {
171            format!("\n{}", " ".repeat(3*lvl))
172        } else {
173            "".to_owned()
174        };
175        if is_part {self.core.write("(");}
176        let mut expr_iter = exprs.iter().peekable();
177        while let Some(expr) = expr_iter.next() {
178            self.add_logic_expr(expr, 0, true);
179            if expr_iter.peek().is_some() {
180                self.core.write(op);
181                self.core.write(&eol);
182            }
183        }
184        if is_part {self.core.write(")");}
185    }
186
187    fn add_expr_id(&mut self, expr: &ExprId) {
188        self.core.write(&expr.name);
189        if let Some(idx) = expr.idx {
190            self.core.write(&format!("[{idx}]"));
191        }
192        if let Some(field) = &expr.field {
193            self.core.write(".");
194            self.core.write(field);
195        }
196        if let Some(r) = &expr.range {
197            if let Some(msb) = r.msb {
198                self.core.write(&format!("[{msb}:{}]", r.lsb));
199            } else {
200                self.core.write(&format!("[{}]",r.lsb));
201            }
202        }
203    }
204
205}
206
207impl GeneratorHw for GeneratorSv {
208
209    /// Write generic header for a file
210    fn write_file_header(&mut self) {
211        // Add header : TODO: configurable header
212        self.write_comment(0, "File generated automatically: DO NOT EDIT.");
213        self.write("\n");
214    }
215
216    fn write_pkg_header(&mut self, name: &str) {
217        self.write(&format!("package {name}_pkg;\n\n"));
218    }
219    fn write_pkg_footer(&mut self, name: &str) {
220        self.write(&format!("endpackage : {name}_pkg\n"));
221    }
222
223    fn write_const(&mut self, signal: &SignalDecl, value: LogicExpr) {
224        self.write("   localparam ");
225        match &signal.def.kind {
226            SignalKind::Unsigned(1) => self.write("bit "),
227            SignalKind::Unsigned(w) => self.write(&format!("logic [{}:0] ", w-1)),
228            SignalKind::Integer     => self.write("int "),
229            _ => unreachable!("Constant were supposed to be only unsigned or int got {:?}", signal.def.kind)
230        }
231        self.write(&signal.def.name);
232        self.write(" = ");
233        match &value {
234            LogicExpr::ValueU(v,w) => {
235                if signal.name().ends_with("_W") {
236                    self.write(&format!("{v:2}"))
237                } else if signal.def.kind==SignalKind::Unsigned(1) {
238                    self.write(&format!("{v}"))
239                } else {
240                    let n = (w+3)>>2;
241                    self.write(&format!("{w}'h{v:0n$x}"))
242                }
243            },
244            LogicExpr::ValueI(v,w) => {
245                if matches!(signal.def.kind,SignalKind::Integer | SignalKind::Unsigned(1)) {
246                    self.write(&format!("{v}"))
247                } else {
248                    let n = (w+3)>>2;
249                    self.write(&format!("{w}'sh{v:0n$x}"))
250                }
251            }
252            _ => self.add_logic_expr(&value, 0, false),
253        }
254        self.write(";\n");
255    }
256
257    // Enums declaration
258    fn write_enum_header(&mut self, _name: &str, width: u8) {
259        self.write("   typedef enum logic ");
260        if width > 1 {
261            self.write(&format!("[{}:0] ", width - 1));
262        }
263        self.write("{\n");
264    }
265
266    fn write_enum_entry(&mut self, entry: &EnumEntry, is_last: bool) {
267        self.write(&format!("      {} = {}", entry.name, entry.value));
268        self.write(if is_last {" "} else {","});
269        self.write(" // ");
270        self.write(&entry.description.get_short(false));
271        self.write("\n");
272    }
273
274    fn write_enum_footer(&mut self, name: &str, _width: u8) {
275        self.write("   } ");
276        self.write(name);
277        self.write(";\n\n");
278    }
279
280    // Structure declaration
281    fn write_struct_header(&mut self, _name: &str, fields: &[SignalDecl]) {
282        let has_array = fields.iter().any(|f| f.def.dim > 0);
283        let packed = if has_array { "" } else { "packed " };
284        self.write(&format!("   typedef struct {packed}{{\n"));
285    }
286
287    fn write_struct_field(&mut self, field: &SignalDecl, _is_last: bool) {
288        self.write("      ");
289        self.add_signal_def(&field.def, None);
290        self.write(";");
291        if !field.desc.is_empty() {
292            self.write(" // ");
293            self.write(&field.desc);
294        }
295        self.write("\n");
296    }
297
298    fn write_struct_footer(&mut self, name: &str) {
299        self.write(&format!("   }} {name};\n\n"));
300    }
301
302    // Module declaration
303    fn write_module_decl_header(&mut self, name: &str) {
304        self.write(&format!("module {name} (\n"));
305    }
306
307    fn write_module_decl_footer(&mut self, _name: &str) {
308        self.write(");\n");
309    }
310
311    fn write_module_impl_footer(&mut self, name: &str) {
312        self.write(&format!("\nendmodule : {name}\n"));
313    }
314
315    fn write_port_decl(&mut self, port: &PortInfo, prefix: Option<&String>, is_last: bool) {
316        self.write("   ");
317        match &port.dir {
318            PortDir::In  => self.write("input  var "),
319            PortDir::Out => self.write("output var "),
320            PortDir::Modport(mp) => {
321                let SignalKind::Custom((None,intf)) = &port.def.kind else {panic!("Expecting interface for port {:?}", port.def.kind)};
322                self.write(&format!("{intf}.{mp} "))
323            }
324        }
325        if port.dir.is_modport() {
326            self.write(port.name());
327        } else {
328            self.add_signal_def(&port.def, prefix);
329        }
330        self.write(if is_last {"  "} else {", "});
331        if !port.desc.is_empty() {
332            self.write("// ");
333            self.write(&port.desc);
334        }
335        self.write("\n");
336    }
337
338    fn write_signal_decl(&mut self, signal: &SignalDecl) {
339        self.write("   ");
340        self.add_signal_def(&signal.def, None);
341        self.write(";");
342        if !signal.desc.is_empty() {
343            self.write(" // ");
344            self.write(&signal.desc);
345        }
346        self.write("\n");
347    }
348
349    fn write_rif_decl(&mut self, comp: &CompInfo, single: bool, clk: &str, rst: &str) {
350        let name = if single {"rif"} else {&comp.name};
351        self.write(&format!("   rif_if#({}, {}) if_{name}({clk}, {rst});\n",
352            comp.addr_width, comp.data_width
353        ));
354    }
355
356    fn write_inst_header(&mut self, type_name: &str, inst_name: &str, params: &[(String, isize)]) {
357        self.is_bridge = inst_name=="bridge";
358        self.write(&format!("   {type_name}"));
359        if !params.is_empty() {
360            self.write("#(");
361            let mut iter = params.iter().map(|(_,v)| v).peekable();
362            while let Some(v) = iter.next() {
363                self.write(&format!("{v}"));
364                if iter.peek().is_some() {
365                    self.write(", ");
366                }
367            }
368            self.write(")");
369        }
370        self.write(&format!(" i_{inst_name} ("));
371        if !self.is_bridge {
372            self.write("\n");
373        }
374    }
375
376    fn write_port_bind(&mut self, port_name: &str, signal_name: &str, is_last: bool) {
377        let eol = if self.is_bridge {" "} else {"\n"};
378        if port_name=="*" {
379            self.write(".*")
380        } else {
381            if !self.is_bridge {
382                self.write("      ");
383            }
384            self.write(&format!(".{port_name}({signal_name})"));
385        }
386        if is_last {
387            self.write(eol);
388            if !self.is_bridge {
389                self.write("   ");
390            }
391            self.write(");\n\n");
392        } else {
393            self.write(",");
394            self.write(eol);
395        }
396    }
397
398    fn write_intf_bind(&mut self, name: &str, is_last: bool) {
399        self.write(&format!("      .if_rif(if_{name})"));
400        if is_last {
401            self.write("\n   );\n\n");
402        } else {
403            self.write(",\n");
404        }
405    }
406
407    fn write_assign(&mut self, lhs: ExprId, rhs: LogicExpr) {
408        self.write("   assign ");
409        self.add_expr_id(&lhs);
410        self.write(" = ");
411        let multiline =
412            (rhs.has_vec() && rhs.nb() > 2 && !rhs.is_and()) ||
413            (rhs.is_ite() && (rhs.nb() > 1 || !rhs.is_else_value()));
414        let lvl = if multiline {self.write("\n"); 2} else {0};
415        self.add_logic_expr(&rhs, lvl, false);
416        self.write(";\n");
417    }
418
419    // Combinatorial process
420    fn write_process_comb_header(&mut self, name: &str) {
421        self.write(&format!("\n   always_comb begin : proc_{name}\n"));
422    }
423    fn write_process_comb_footer(&mut self, _name: &str) {
424        self.write("   end\n\n");
425    }
426
427    fn write_match_header(&mut self, name: &str) {
428        self.write(&format!("      case({name})\n"));
429    }
430
431    fn write_match_footer(&mut self) {
432        self.write("   endcase\n");
433    }
434
435    fn write_match_case_header(&mut self, value: LogicExpr) {
436        self.write("         ");
437        self.add_logic_expr(&value, 0, false);
438        self.write(" : begin\n");
439    }
440
441    fn write_match_case_footer(&mut self) {
442        self.write("         end\n");
443    }
444
445    fn write_cond_if(&mut self, lvl: usize, cond: LogicExpr) {
446        self.write(&" ".repeat(3*lvl));
447        self.write("if(");
448        self.add_logic_expr(&cond, 0, false);
449        self.write(") begin\n");
450    }
451
452    fn write_cond_else(&mut self, lvl: usize, cond: Option<LogicExpr>) {
453        self.write(&" ".repeat(3*lvl));
454        self.write("else ");
455        if let Some(cond) = cond {
456            self.write_cond_if(0, cond);
457        } else {
458            self.write("begin\n");
459        }
460    }
461
462    fn write_cond_end(&mut self, lvl: usize) {
463        self.write(&" ".repeat(3*lvl));
464        self.write("end\n");
465    }
466
467    fn write_assign_comb(&mut self, lvl: usize, lhs: ExprId, rhs: LogicExpr) {
468        self.write(&" ".repeat(3*lvl));
469        self.add_expr_id(&lhs);
470        self.write(" = ");
471        self.add_logic_expr(&rhs, 0, false);
472        self.write(";\n");
473    }
474
475    fn write_comment(&mut self, lvl: usize, txt: &str) {
476        self.write(&" ".repeat(3*lvl));
477        self.write("// ");
478        self.write(txt);
479        self.write("\n");
480    }
481
482    fn write_comment_box(&mut self, txt: &str) {
483        self.write("\n//-----------------------------------------------------------------------------\n");
484        for l in txt.split('\n') {
485            self.write("// ");
486            self.write(l);
487            self.write("\n");
488        }
489        self.write("//-----------------------------------------------------------------------------\n");
490    }
491
492
493    fn write_process_seq(&mut self, clk: &str, rst: &ResetDef, name: &str, signals: &[SignalInfo]) {
494        // Check all signals clear/enable o see if all signals share a condition or not
495        let mut signals_iter = signals.iter();
496        let (clk_en, clr): (Option<&LogicExpr>, Option<&LogicExpr>) =
497            if let Some(signal) = signals_iter.next() {
498                (signal.enable.as_ref(), signal.clear.as_ref())
499            } else {
500                (None, None)
501            };
502        let mut clk_en_global = true;
503        let mut clr_global = true;
504        for signal in signals_iter {
505            if clk_en_global {
506                if let (Some(new), Some(base)) = (signal.enable.as_ref(), clk_en) {
507                    if new != base {
508                        clk_en_global = false;
509                    }
510                } else if clk_en.is_some() != signal.enable.is_some() {
511                    clk_en_global = false;
512                }
513            }
514            if clr_global {
515                if let Some(n) = &signal.clear {
516                    if clr.is_none() || n != clr.unwrap() {
517                        clr_global = false;
518                    }
519                } else if clr.is_some() {
520                    clr_global = false;
521                }
522            }
523        }
524        // Declaration
525        self.write(&format!("\n   always_ff @(posedge {clk}"));
526        if !rst.sync {
527            let pol = if rst.active_high { "pos" } else { "neg" };
528            self.write(&format!(" or {pol}edge {}", rst.name));
529        }
530        self.write(&format!(") begin : {name}\n      if("));
531        // Reset
532        if !rst.active_high {
533            self.write("!");
534        }
535        self.write(&format!("{}) begin\n", rst.name));
536        for signal in signals.iter() {
537            self.write_signal_seq(&signal.name, &signal.reset, 3);
538        }
539        self.write("      end else ");
540        // Optional Global clear
541        // Maybe need to add an option to take the clear into account only if the enable is high
542        if let Some(clr) = clr.filter(|_| clr_global) {
543            self.write("if(");
544            self.add_logic_expr(clr, 0, false);
545            self.write(") begin\n");
546            for signal in signals.iter() {
547                self.write_signal_seq(&signal.name, &signal.reset, 3);
548            }
549            self.write("      end else ");
550        }
551        // Optional Global Enable
552        if let Some(clk_en) = clk_en.filter(|_| clk_en_global) {
553            self.write("if(");
554            self.add_logic_expr(clk_en, 0, false);
555            self.write(") ");
556        }
557        self.write("begin\n");
558        // Set value
559        let mut lvl = 3;
560        for signal in signals.iter() {
561            if let Some(clr) = signal.clear.as_ref().filter(|_| !clr_global) {
562                lvl = 4;
563                self.write("         if(");
564                self.add_logic_expr(clr, 0, false);
565                self.write(")\n");
566                self.write_signal_seq(&signal.name, &signal.reset, lvl);
567                self.write("         else");
568            }
569            if let Some(clk_en) = signal.enable.as_ref().filter(|_| !clk_en_global) {
570                if lvl==3 {
571                    self.write("         ");
572                }
573                self.write("if(");
574                self.add_logic_expr(clk_en, 0, false);
575                self.write(")");
576                lvl = 4;
577            }
578            if lvl==4 {
579                self.write("\n");
580            }
581            self.write_signal_seq(&signal.name, &signal.value, lvl);
582            lvl = 3;
583        }
584        self.write("      end\n   end\n\n");
585    }
586
587}