futilehdl/src/rtlil.rs

176 lines
4.1 KiB
Rust
Raw Normal View History

2022-01-01 21:43:38 +00:00
#[derive(Debug, Default)]
pub struct ILWriter {
data: String,
indent: usize,
}
// this would be much nicer if indent gave you a new writer
// which would indent things
impl ILWriter {
2022-01-04 22:05:25 +00:00
pub fn new() -> Self {
2022-01-01 21:43:38 +00:00
Default::default()
}
2022-01-04 22:05:25 +00:00
pub fn write_line(&mut self, line: &str) {
2022-01-01 21:43:38 +00:00
self.data += &"\t".repeat(self.indent);
self.data += line;
self.data += "\n";
}
2022-01-04 22:05:25 +00:00
pub fn indent(&mut self) {
2022-01-01 21:43:38 +00:00
self.indent += 1
}
2022-01-04 22:05:25 +00:00
pub fn dedent(&mut self) {
2022-01-01 21:43:38 +00:00
self.indent = self
.indent
.checked_sub(1)
.expect("tried to dedent negative amount")
}
2022-01-04 22:05:25 +00:00
pub fn finish(self) -> String {
2022-01-01 21:43:38 +00:00
self.data
}
}
// the proper way
2022-01-04 00:38:35 +00:00
#[derive(Debug)]
2022-01-04 22:05:25 +00:00
pub enum PortOption {
2022-01-01 21:43:38 +00:00
Input(i32),
Output(i32),
}
2022-01-04 00:38:35 +00:00
#[derive(Debug)]
2022-01-01 21:43:38 +00:00
pub struct Wire {
2022-01-04 22:05:25 +00:00
/// rtlil ID
2022-01-01 21:43:38 +00:00
id: String,
2022-01-04 22:05:25 +00:00
/// width in bits
width: u32,
/// Port info if this is a port
2022-01-05 01:09:08 +00:00
port_info: Option<PortOption>,
2022-01-01 21:43:38 +00:00
}
2022-01-04 00:38:35 +00:00
impl Wire {
2022-01-04 22:05:25 +00:00
pub fn new(id: impl Into<String>, width: u32, port_info: Option<PortOption>) -> Self {
2022-01-04 00:38:35 +00:00
Wire {
id: id.into(),
2022-01-04 22:05:25 +00:00
width,
2022-01-05 01:09:08 +00:00
port_info,
2022-01-04 00:38:35 +00:00
}
}
fn write_rtlil(&self, writer: &mut ILWriter) {
let mut line = String::from("wire ");
2022-01-04 22:05:25 +00:00
if let Some(option) = &self.port_info {
let port_str = match option {
PortOption::Input(num) => format!("input {} ", num),
PortOption::Output(num) => format!("output {} ", num),
2022-01-04 00:38:35 +00:00
};
2022-01-04 22:05:25 +00:00
line += &port_str;
};
2022-01-04 00:38:35 +00:00
2022-01-04 22:05:25 +00:00
if self.width > 1 {
line += &format!("width {} ", self.width);
2022-01-04 00:38:35 +00:00
}
line += &self.id;
writer.write_line(&line);
}
}
#[derive(Debug)]
2022-01-04 22:05:25 +00:00
pub struct Module {
2022-01-04 00:38:35 +00:00
name: String,
wires: Vec<Wire>,
cells: Vec<Cell>,
connections: Vec<(String, String)>,
gen_id: i32,
}
2022-01-01 21:43:38 +00:00
2022-01-04 00:38:35 +00:00
impl Module {
2022-01-04 22:05:25 +00:00
pub fn new(name: impl Into<String>) -> Self {
2022-01-04 00:38:35 +00:00
Module {
name: name.into(),
wires: Default::default(),
cells: Default::default(),
connections: Default::default(),
gen_id: 0,
}
}
2022-01-04 22:05:25 +00:00
pub fn add_wire(&mut self, wire: Wire) {
2022-01-04 00:38:35 +00:00
self.wires.push(wire)
}
2022-01-04 22:05:25 +00:00
pub fn add_connection(&mut self, target: String, source: String) {
self.connections.push((target, source))
}
pub fn add_cell(&mut self, cell: Cell) {
self.cells.push(cell)
}
pub fn write_rtlil(&self, writer: &mut ILWriter) {
2022-01-04 00:38:35 +00:00
writer.write_line(&format!("module {}", self.name));
writer.indent();
for wire in &self.wires {
wire.write_rtlil(writer);
}
for cell in &self.cells {
cell.write_rtlil(writer);
}
for conn in &self.connections {
writer.write_line(&format!("connect {} {}", conn.0, conn.1))
}
writer.dedent();
writer.write_line("end");
}
2022-01-04 22:05:25 +00:00
pub fn make_genid(&mut self, stem: &str) -> String {
2022-01-04 00:38:35 +00:00
let res = format!("${}${}", stem, self.gen_id);
self.gen_id += 1;
res
}
}
#[derive(Debug)]
2022-01-04 22:05:25 +00:00
pub struct Cell {
2022-01-01 21:43:38 +00:00
id: String,
celltype: String,
parameters: Vec<(String, String)>,
connections: Vec<(String, String)>,
}
impl Cell {
2022-01-04 22:05:25 +00:00
pub fn new(id: &str, celltype: &str) -> Self {
2022-01-01 21:43:38 +00:00
Cell {
id: id.into(),
celltype: celltype.into(),
parameters: Vec::new(),
connections: Vec::new(),
}
}
2022-01-04 22:05:25 +00:00
pub fn add_param(&mut self, name: &str, value: &str) {
2022-01-01 21:43:38 +00:00
self.parameters.push((name.into(), value.into()))
}
2022-01-04 22:05:25 +00:00
pub fn add_connection(&mut self, from: &str, to: &str) {
2022-01-01 21:43:38 +00:00
self.connections.push((from.into(), to.into()))
}
fn write_rtlil(&self, writer: &mut ILWriter) {
writer.write_line(&format!("cell {} {}", self.celltype, self.id));
writer.indent();
for param in &self.parameters {
writer.write_line(&format!("parameter {} {}", param.0, param.1))
}
for conn in &self.connections {
writer.write_line(&format!("connect {} {}", conn.0, conn.1))
}
writer.dedent();
writer.write_line("end");
}
}