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 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 );
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 fn write_file_header(&mut self) {
211 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 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 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 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 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 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 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 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 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 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 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}