1use crate::stmt::Stmt;
2
3pub trait Extension {
4 fn add(self, module: Module) -> Module;
5}
6
7#[derive(Debug, Clone)]
10pub struct Module {
11 name: String,
12 params: Vec<Param>,
13 ports: Vec<Port>,
14 blocks: Vec<Block>,
15 pub(crate) clock: String, pub(crate) reset: String, }
18
19impl Module {
20 pub fn new(name: impl ToString, clock: impl ToString, reset: impl ToString) -> Self {
21 Self {
22 name: name.to_string(),
23 params: vec![],
24 ports: vec![],
25 blocks: vec![],
26 clock: clock.to_string(),
27 reset: reset.to_string(),
28 }
29 }
30 pub fn input(mut self, name: impl ToString, width: usize) -> Self {
31 assert!(width > 0);
32 self.ports.push(Port::input(name, width, 1));
33 self
34 }
35 pub fn output(mut self, name: impl ToString, width: usize) -> Self {
36 assert!(width > 0);
37 self.ports.push(Port::output(name, width, 1));
38 self
39 }
40 pub fn inout(mut self, name: impl ToString, width: usize) -> Self {
41 assert!(width > 0);
42 self.ports.push(Port::inout(name, width, 1));
43 self
44 }
45 pub fn param(mut self, name: impl ToString, default: Option<impl ToString>) -> Self {
46 self.params.push(Param::new(name, default));
47 self
48 }
49 pub fn lparam(mut self, name: impl ToString, val: impl ToString) -> Self {
50 self.blocks.push(Block::LocalParam(LocalParam::new(
51 name.to_string(),
52 val.to_string(),
53 )));
54 self
55 }
56 pub fn logic(mut self, name: impl ToString, bit: usize, len: usize) -> Self {
57 self.blocks.push(Block::Logic(Logic::new(name, bit, len)));
58 self
59 }
60 pub fn instant(mut self, inst: Instant) -> Self {
61 self.blocks.push(Block::Instant(inst));
62 self
63 }
64 pub fn always_comb(mut self, stmt: Stmt) -> Self {
65 self.blocks.push(Block::AlwaysComb(AlwaysComb::new(stmt)));
66 self
67 }
68 pub fn always_ff(mut self, edges: Sens, stmt: Stmt) -> Self {
69 self.blocks
70 .push(Block::AlwaysFF(AlwaysFF::new(edges, stmt)));
71 self
72 }
73
74 pub fn add<E: Extension>(self, ext: E) -> Self {
75 ext.add(self)
76 }
77}
78
79impl Module {
80 pub fn verilog(&self) -> Vec<String> {
81 let mut code: Vec<String> = vec![];
82 code.extend(self.module_header());
83
84 for stmt in &self.blocks {
85 for line in stmt.verilog() {
86 code.push(format!(" {line}"))
87 }
88 }
89
90 code.extend(self.module_footer());
91 code
92 }
93
94 pub fn verilog_sorted(&self) -> Vec<String> {
95 let mut code: Vec<String> = vec![];
96 code.extend(self.module_header());
97
98 for stmt in &self.blocks {
100 if matches!(stmt, Block::LocalParam(_)) {
101 for line in stmt.verilog() {
102 code.push(format!(" {line}"))
103 }
104 }
105 }
106
107 for stmt in &self.blocks {
109 if matches!(stmt, Block::Logic(_)) {
110 for line in stmt.verilog() {
111 code.push(format!(" {line}"))
112 }
113 }
114 }
115
116 for stmt in &self.blocks {
118 if matches!(stmt, Block::Instant(_))
119 | matches!(stmt, Block::AlwaysFF(_))
120 | matches!(stmt, Block::AlwaysComb(_))
121 {
122 for line in stmt.verilog() {
123 code.push(format!(" {line}"))
124 }
125 }
126 }
127
128 code.extend(self.module_footer());
129 code
130 }
131
132 fn module_header(&self) -> Vec<String> {
133 let mut code: Vec<String> = Vec::new();
134 code.push(format!("module {}", self.name));
135
136 if self.params.len() > 0 {
138 code.push(format!("#("));
139 for (i, param) in self.params.iter().enumerate() {
140 if i < self.params.len() - 1 {
141 code.push(format!(" {},", param.verilog()));
142 } else {
143 code.push(format!(" {}", param.verilog()));
144 }
145 }
146 code.push(format!(")"));
147 }
148
149 if self.ports.len() > 0 {
151 code.push(format!("("));
152 for (i, port) in self.ports.iter().enumerate() {
153 if i < self.ports.len() - 1 {
154 code.push(format!(" {},", port.verilog()));
155 } else {
156 code.push(format!(" {}", port.verilog()));
157 }
158 }
159 code.push(format!(")"));
160 }
161
162 code.push(format!(";"));
163 code
164 }
165
166 fn module_footer(&self) -> Vec<String> {
167 vec![format!("endmodule")]
168 }
169}
170
171#[derive(Debug, Clone)]
174struct Port {
175 name: String,
176 direct: Direct,
177 bit: usize,
178 len: usize,
179}
180
181impl Port {
182 fn input(name: impl ToString, bit: usize, len: usize) -> Self {
183 Self {
184 name: name.to_string(),
185 direct: Direct::In,
186 bit,
187 len,
188 }
189 }
190 fn output(name: impl ToString, bit: usize, len: usize) -> Self {
191 Self {
192 name: name.to_string(),
193 direct: Direct::Out,
194 bit,
195 len,
196 }
197 }
198 fn inout(name: impl ToString, bit: usize, len: usize) -> Self {
199 Self {
200 name: name.to_string(),
201 direct: Direct::InOut,
202 bit,
203 len,
204 }
205 }
206}
207
208impl Port {
209 fn verilog(&self) -> String {
210 let bit = if self.bit == 1 {
211 format!(" ")
212 } else {
213 format!("[{:>2}:0] ", self.bit - 1)
214 };
215 let len = if self.len == 1 {
216 format!("")
217 } else {
218 format!("[{:>2}:0]", self.len - 1)
219 };
220 format!(
221 "{:<6} logic {}{}{}",
222 self.direct.verilog(),
223 bit,
224 self.name,
225 len
226 )
227 }
228}
229
230#[derive(Debug, Clone, Copy)]
231enum Direct {
232 In,
233 Out,
234 InOut,
235}
236
237impl Direct {
238 fn verilog(&self) -> String {
239 match self {
240 Direct::In => format!("input"),
241 Direct::Out => format!("output"),
242 Direct::InOut => format!("inout"),
243 }
244 }
245}
246
247#[derive(Debug, Clone)]
250struct Param {
251 name: String,
252 default: Option<String>,
253}
254
255impl Param {
256 fn new(name: impl ToString, default: Option<impl ToString>) -> Self {
257 Self {
258 name: name.to_string(),
259 default: default.map(|s| s.to_string()),
260 }
261 }
262 fn verilog(&self) -> String {
263 match &self.default {
264 Some(default) => format!("parameter {} = {}", self.name, default),
265 None => format!("parameter {}", self.name),
266 }
267 }
268}
269
270#[derive(Debug, Clone)]
273enum Block {
274 LocalParam(LocalParam),
275 Logic(Logic),
276 Instant(Instant),
277 AlwaysFF(AlwaysFF),
278 AlwaysComb(AlwaysComb),
279}
280
281impl Block {
282 fn verilog(&self) -> Vec<String> {
283 match self {
284 Block::LocalParam(e) => e.verilog(),
285 Block::Logic(e) => e.verilog(),
286 Block::Instant(e) => e.verilog(),
287 Block::AlwaysFF(e) => e.verilog(),
288 Block::AlwaysComb(e) => e.verilog(),
289 }
290 }
291}
292
293#[derive(Debug, Clone)]
296struct LocalParam {
297 name: String,
298 val: String,
299}
300
301impl LocalParam {
302 fn new<S: ToString>(name: S, val: S) -> Self {
303 Self {
304 name: name.to_string(),
305 val: val.to_string(),
306 }
307 }
308}
309
310impl LocalParam {
311 fn verilog(&self) -> Vec<String> {
312 vec![format!("localparam {} = {};", self.name, self.val)]
313 }
314}
315
316#[derive(Debug, Clone)]
319struct Logic {
320 name: String,
321 bit: usize,
322 len: usize,
323}
324
325impl Logic {
326 fn new(name: impl ToString, bit: usize, len: usize) -> Self {
327 Self {
328 name: name.to_string(),
329 bit,
330 len,
331 }
332 }
333}
334
335impl Logic {
336 fn verilog(&self) -> Vec<String> {
337 let bit = if self.bit == 1 {
338 format!(" ")
339 } else {
340 format!("[{:>2}:0] ", self.bit - 1)
341 };
342 let len = if self.len == 1 {
343 format!("")
344 } else {
345 format!("[{:>2}:0]", self.len - 1)
346 };
347 vec![format!("logic {}{}{};", bit, self.name, len)]
348 }
349}
350
351#[derive(Debug, Clone)]
354pub struct Instant {
355 name: String,
356 module: String,
357 params: Vec<(String, String)>,
358 ports: Vec<(String, String)>,
359}
360
361impl Instant {
362 pub fn new(name: impl ToString, module: impl ToString) -> Self {
363 Self {
364 name: name.to_string(),
365 module: module.to_string(),
366 params: vec![],
367 ports: vec![],
368 }
369 }
370 pub fn param(mut self, param: impl ToString, val: impl ToString) -> Self {
371 self.params.push((param.to_string(), val.to_string()));
372 self
373 }
374 pub fn port(mut self, port: impl ToString, wire: impl ToString) -> Self {
375 self.ports.push((port.to_string(), wire.to_string()));
376 self
377 }
378}
379
380impl Instant {
381 fn verilog(&self) -> Vec<String> {
382 let mut code: Vec<String> = Vec::new();
383
384 code.push(format!("{} #(", self.module));
385
386 for (i, (param, value)) in self.params.iter().enumerate() {
387 let sep = if i < self.params.len() - 1 { "," } else { "" };
388 code.push(format!(" .{}({}){}", param, value, sep));
389 }
390
391 code.push(format!(") {} (", self.name));
392
393 for (i, (port, value)) in self.ports.iter().enumerate() {
394 let sep = if i < self.ports.len() - 1 { "," } else { "" };
395 code.push(format!(" .{}({}){}", port, value, sep));
396 }
397
398 code.push(format!(");"));
399
400 code
401 }
402}
403
404#[test]
405fn test_instant() {
406 let obj = Instant::new("i_hoge", "hoge")
407 .port("clk", "clk")
408 .port("rstn", "rstn")
409 .param("a", "hoge");
410 println!("{}", obj.verilog().join("\n"));
411}
412
413#[derive(Debug, Clone)]
416pub struct AlwaysFF {
417 sens: Sens,
418 stmt: Stmt,
419}
420
421impl AlwaysFF {
422 pub fn new(sens: Sens, stmt: Stmt) -> Self {
423 Self { sens, stmt }
424 }
425}
426
427impl AlwaysFF {
428 fn verilog(&self) -> Vec<String> {
429 let mut code = Vec::<String>::new();
430 code.push(format!("always_ff @({})", self.sens.verilog()));
431 code.extend(self.stmt.blocking().iter().map(|s| format!(" {s}")));
432 code
433 }
434}
435
436#[derive(Debug, Clone)]
437pub struct Sens {
438 edges: Vec<Edge>,
439}
440
441impl Sens {
442 pub fn new() -> Self {
443 Self { edges: vec![] }
444 }
445 pub fn posedge(mut self, wire: impl ToString) -> Self {
446 self.edges.push(Edge::Posedge(wire.to_string()));
447 self
448 }
449 pub fn negedge(mut self, wire: impl ToString) -> Self {
450 self.edges.push(Edge::Negedge(wire.to_string()));
451 self
452 }
453 pub fn bothedge(mut self, wire: impl ToString) -> Self {
454 self.edges.push(Edge::Bothedge(wire.to_string()));
455 self
456 }
457}
458
459impl Sens {
460 fn verilog(&self) -> String {
461 self.edges
462 .iter()
463 .map(|edge| edge.verilog())
464 .collect::<Vec<_>>()
465 .join(" or ")
466 }
467}
468
469#[derive(Debug, Clone)]
470enum Edge {
471 Posedge(String),
472 Negedge(String),
473 Bothedge(String),
474}
475
476impl Edge {
477 fn verilog(&self) -> String {
478 match self {
479 Edge::Posedge(s) => format!("posedge {s}"),
480 Edge::Negedge(s) => format!("negedge {s}"),
481 Edge::Bothedge(s) => format!("{s}"),
482 }
483 }
484}
485
486#[derive(Debug, Clone)]
489pub struct AlwaysComb {
490 stmt: Stmt,
491}
492
493impl AlwaysComb {
494 pub fn new(stmt: Stmt) -> Self {
495 Self { stmt }
496 }
497}
498
499impl AlwaysComb {
500 fn verilog(&self) -> Vec<String> {
501 let mut code = Vec::<String>::new();
502 code.push(format!("always_comb"));
503 code.extend(self.stmt.nonblocking().iter().map(|s| format!(" {s}")));
504 code
505 }
506}