mirror of
https://github.com/alex-s168/turbo-blif.git
synced 2025-09-10 10:05:08 +02:00
yosys extensions
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
# turbo-blif
|
# turbo-blif
|
||||||
|
|
||||||
low-memory-usage BLIF (berkeley logic interchange format) parser and writer.
|
low-memory-usage BLIF (berkeley logic interchange format) parser.
|
||||||
|
|
||||||
supports:
|
supports:
|
||||||
- the latest BLIF specification (dated July 28, 1992)
|
- the latest BLIF specification (dated July 28, 1992)
|
||||||
- all yosys BLIF extensions
|
- all yosys BLIF extensions
|
||||||
(supports reading of BLIF files generated with `write_blif -iname -iattr -param -cname -blackbox -attr -conn -icells`)
|
(supports reading of BLIF files generated with `write_blif -iname -iattr -param -cname -blackbox -attr -conn`)
|
||||||
- KISS state machines (which yosys doesn't even support)
|
- KISS state machines (which yosys doesn't even support)
|
||||||
- clock and delay constraints (yosys just ignores those)
|
- clock and delay constraints (yosys just ignores those)
|
||||||
|
|
||||||
|
82
src/ast.rs
82
src/ast.rs
@@ -80,7 +80,23 @@ impl FSMConsumer for FSM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)]
|
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)]
|
||||||
pub enum ModelCmd {
|
pub enum CellAttrAst {
|
||||||
|
/// non-standard; emitted by: yosys
|
||||||
|
CellName(String),
|
||||||
|
|
||||||
|
/// non-standard; possibly emitted by: yosys
|
||||||
|
///
|
||||||
|
/// example: Attr { key: "src", val: "\"some/file.v:320.20-320.28\"" }
|
||||||
|
Attr { key: Str<8>, val: String },
|
||||||
|
|
||||||
|
/// non-standard; emitted by: yosys
|
||||||
|
///
|
||||||
|
/// example: Param { key: "A_WIDTH", val: "00000000000000000000000000000001" }
|
||||||
|
Param { key: Str<16>, val: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)]
|
||||||
|
pub enum ModelCmdKind {
|
||||||
Gate(Gate),
|
Gate(Gate),
|
||||||
FF(FlipFlop),
|
FF(FlipFlop),
|
||||||
LibGate(LibGate),
|
LibGate(LibGate),
|
||||||
@@ -90,6 +106,25 @@ pub enum ModelCmd {
|
|||||||
name: Str<32>,
|
name: Str<32>,
|
||||||
map: Vec<(Str<16>, Str<16>)>,
|
map: Vec<(Str<16>, Str<16>)>,
|
||||||
},
|
},
|
||||||
|
Connect {
|
||||||
|
from: Str<16>,
|
||||||
|
to: Str<16>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)]
|
||||||
|
pub struct ModelCmd {
|
||||||
|
pub kind: ModelCmdKind,
|
||||||
|
pub attrs: Vec<CellAttrAst>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ModelCmdKind> for ModelCmd {
|
||||||
|
fn from(value: ModelCmdKind) -> Self {
|
||||||
|
Self {
|
||||||
|
kind: value,
|
||||||
|
attrs: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)]
|
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)]
|
||||||
@@ -106,26 +141,29 @@ impl CommandConsumer for Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn gate_done(&mut self, gate: Self::Gate) {
|
fn gate_done(&mut self, gate: Self::Gate) {
|
||||||
self.commands.push(ModelCmd::Gate(gate));
|
self.commands.push(ModelCmdKind::Gate(gate).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ff(&mut self, ff: FlipFlop) {
|
fn ff(&mut self, ff: FlipFlop) {
|
||||||
self.commands.push(ModelCmd::FF(ff));
|
self.commands.push(ModelCmdKind::FF(ff).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lib_gate(&mut self, gate: LibGate) {
|
fn lib_gate(&mut self, gate: LibGate) {
|
||||||
self.commands.push(ModelCmd::LibGate(gate));
|
self.commands.push(ModelCmdKind::LibGate(gate).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lib_ff(&mut self, ff: LibFlipFlop) {
|
fn lib_ff(&mut self, ff: LibFlipFlop) {
|
||||||
self.commands.push(ModelCmd::LibFF(ff));
|
self.commands.push(ModelCmdKind::LibFF(ff).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub_model(&mut self, model: &str, map: Vec<(Str<16>, Str<16>)>) {
|
fn sub_model(&mut self, model: &str, map: Vec<(Str<16>, Str<16>)>) {
|
||||||
self.commands.push(ModelCmd::SubModel {
|
self.commands.push(
|
||||||
name: model.into(),
|
ModelCmdKind::SubModel {
|
||||||
map,
|
name: model.into(),
|
||||||
});
|
map,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type FSM = FSM;
|
type FSM = FSM;
|
||||||
@@ -150,7 +188,31 @@ impl CommandConsumer for Model {
|
|||||||
let mut fsm = fsm;
|
let mut fsm = fsm;
|
||||||
fsm.physical_latch_order = physical_latch_order;
|
fsm.physical_latch_order = physical_latch_order;
|
||||||
fsm.state_assignments = state_assignments;
|
fsm.state_assignments = state_assignments;
|
||||||
self.commands.push(ModelCmd::FSM(fsm));
|
self.commands.push(ModelCmdKind::FSM(fsm).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attr(&mut self, attr: CellAttr) {
|
||||||
|
self.commands.last_mut().unwrap().attrs.push(match attr {
|
||||||
|
CellAttr::CellName(n) => CellAttrAst::CellName(n.into()),
|
||||||
|
CellAttr::Attr { key, val } => CellAttrAst::Attr {
|
||||||
|
key: key.into(),
|
||||||
|
val: val.into(),
|
||||||
|
},
|
||||||
|
CellAttr::Param { key, val } => CellAttrAst::Param {
|
||||||
|
key: key.into(),
|
||||||
|
val: val.into(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect(&mut self, from: &str, to: &str) {
|
||||||
|
self.commands.push(
|
||||||
|
ModelCmdKind::Connect {
|
||||||
|
from: from.into(),
|
||||||
|
to: to.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
82
src/lib.rs
82
src/lib.rs
@@ -63,6 +63,22 @@ pub trait FSMConsumer {
|
|||||||
fn add_transition(&mut self, transition: FSMTransition);
|
fn add_transition(&mut self, transition: FSMTransition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)]
|
||||||
|
pub enum CellAttr<'a> {
|
||||||
|
/// non-standard; emitted by: yosys
|
||||||
|
CellName(&'a str),
|
||||||
|
|
||||||
|
/// non-standard; possibly emitted by: yosys
|
||||||
|
///
|
||||||
|
/// example: Attr { key: "src", val: "\"some/file.v:320.20-320.28\"" }
|
||||||
|
Attr { key: &'a str, val: &'a str },
|
||||||
|
|
||||||
|
/// non-standard; emitted by: yosys
|
||||||
|
///
|
||||||
|
/// example: Param { key: "A_WIDTH", val: "00000000000000000000000000000001" }
|
||||||
|
Param { key: &'a str, val: &'a str },
|
||||||
|
}
|
||||||
|
|
||||||
pub trait CommandConsumer {
|
pub trait CommandConsumer {
|
||||||
type Gate: GateLutConsumer;
|
type Gate: GateLutConsumer;
|
||||||
type FSM: FSMConsumer;
|
type FSM: FSMConsumer;
|
||||||
@@ -84,6 +100,12 @@ pub trait CommandConsumer {
|
|||||||
/// copies the whole circuit of the referenced model, and maps the ins/outs/clocks according to
|
/// copies the whole circuit of the referenced model, and maps the ins/outs/clocks according to
|
||||||
/// [map]
|
/// [map]
|
||||||
fn sub_model(&mut self, model: &str, map: Vec<(Str<16>, Str<16>)>);
|
fn sub_model(&mut self, model: &str, map: Vec<(Str<16>, Str<16>)>);
|
||||||
|
|
||||||
|
/// attach attr to last gate / fsm / ff / libgate / libff / sub_model
|
||||||
|
fn attr(&mut self, attr: CellAttr);
|
||||||
|
|
||||||
|
/// non-standard
|
||||||
|
fn connect(&mut self, from: &str, to: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)]
|
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd)]
|
||||||
@@ -404,7 +426,13 @@ fn parse_mod(
|
|||||||
lines.peek().is_some_and(|x| !x.as_ref().starts_with("."))
|
lines.peek().is_some_and(|x| !x.as_ref().starts_with("."))
|
||||||
} {
|
} {
|
||||||
let l = next_stmt(lines)?.unwrap();
|
let l = next_stmt(lines)?.unwrap();
|
||||||
let (l, r) = l.as_ref().split_once(' ').ok_or(BlifParserError::Invalid)?;
|
let l = l.as_ref();
|
||||||
|
|
||||||
|
let (l, r) = if l.contains(' ') {
|
||||||
|
l.split_once(' ').unwrap()
|
||||||
|
} else {
|
||||||
|
("", l)
|
||||||
|
};
|
||||||
|
|
||||||
let invs = str_to_tristates(l).map_err(|_| BlifParserError::Invalid)?;
|
let invs = str_to_tristates(l).map_err(|_| BlifParserError::Invalid)?;
|
||||||
let outvs = match r {
|
let outvs = match r {
|
||||||
@@ -765,7 +793,59 @@ fn parse_mod(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
".cname" => {
|
||||||
|
let arg = args.next().ok_or(BlifParserError::MissingArgs)?.into();
|
||||||
|
|
||||||
|
if args.next().is_some() {
|
||||||
|
Err(BlifParserError::TooManyArgs)?
|
||||||
|
}
|
||||||
|
|
||||||
|
consumer.attr(CellAttr::CellName(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
".attr" => {
|
||||||
|
let key = args.next().ok_or(BlifParserError::MissingArgs)?.into();
|
||||||
|
|
||||||
|
let val = args.fold(String::new(), |acc, x| {
|
||||||
|
let mut acc = acc;
|
||||||
|
acc.push_str(x);
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
|
||||||
|
consumer.attr(CellAttr::Attr {
|
||||||
|
key,
|
||||||
|
val: val.as_str(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
".param" => {
|
||||||
|
let key = args.next().ok_or(BlifParserError::MissingArgs)?.into();
|
||||||
|
|
||||||
|
let val = args.fold(String::new(), |acc, x| {
|
||||||
|
let mut acc = acc;
|
||||||
|
acc.push_str(x);
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
|
||||||
|
consumer.attr(CellAttr::Param {
|
||||||
|
key,
|
||||||
|
val: val.as_str(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
".conn" => {
|
||||||
|
let from = args.next().ok_or(BlifParserError::MissingArgs)?.into();
|
||||||
|
let to = args.next().ok_or(BlifParserError::MissingArgs)?.into();
|
||||||
|
|
||||||
|
if args.next().is_some() {
|
||||||
|
Err(BlifParserError::TooManyArgs)?
|
||||||
|
}
|
||||||
|
|
||||||
|
consumer.connect(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: clock & delay cst
|
// TODO: clock & delay cst
|
||||||
|
// TODO: .blackblox
|
||||||
_ => Err(BlifParserError::UnknownKw(cmd.to_string()))?,
|
_ => Err(BlifParserError::UnknownKw(cmd.to_string()))?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
262
src/tests.rs
262
src/tests.rs
@@ -24,17 +24,20 @@ fn simple_named() {
|
|||||||
outputs: Some(vec!["c".into()]),
|
outputs: Some(vec!["c".into()]),
|
||||||
clocks: vec![],
|
clocks: vec![],
|
||||||
},
|
},
|
||||||
commands: vec![ModelCmd::Gate(Gate {
|
commands: vec![
|
||||||
meta: GateMeta {
|
ModelCmdKind::Gate(Gate {
|
||||||
inputs: vec!["a".into(), "b".into(),],
|
meta: GateMeta {
|
||||||
output: "c".into(),
|
inputs: vec!["a".into(), "b".into(),],
|
||||||
external_dc: false,
|
output: "c".into(),
|
||||||
},
|
external_dc: false,
|
||||||
lut: LUT(vec![(
|
},
|
||||||
[Tristate::True, Tristate::True].into_iter().collect(),
|
lut: LUT(vec![(
|
||||||
true
|
[Tristate::True, Tristate::True].into_iter().collect(),
|
||||||
)]),
|
true
|
||||||
})],
|
)]),
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
],
|
||||||
})],
|
})],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -60,17 +63,20 @@ fn simple_unnamed() {
|
|||||||
outputs: Some(vec!["c".into()]),
|
outputs: Some(vec!["c".into()]),
|
||||||
clocks: vec![],
|
clocks: vec![],
|
||||||
},
|
},
|
||||||
commands: vec![ModelCmd::Gate(Gate {
|
commands: vec![
|
||||||
meta: GateMeta {
|
ModelCmdKind::Gate(Gate {
|
||||||
inputs: vec!["a".into(), "b".into(),],
|
meta: GateMeta {
|
||||||
output: "c".into(),
|
inputs: vec!["a".into(), "b".into(),],
|
||||||
external_dc: false,
|
output: "c".into(),
|
||||||
},
|
external_dc: false,
|
||||||
lut: LUT(vec![(
|
},
|
||||||
[Tristate::True, Tristate::True].into_iter().collect(),
|
lut: LUT(vec![(
|
||||||
true
|
[Tristate::True, Tristate::True].into_iter().collect(),
|
||||||
)]),
|
true
|
||||||
})],
|
)]),
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
],
|
||||||
})],
|
})],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -95,17 +101,20 @@ c
|
|||||||
outputs: None,
|
outputs: None,
|
||||||
clocks: vec![],
|
clocks: vec![],
|
||||||
},
|
},
|
||||||
commands: vec![ModelCmd::Gate(Gate {
|
commands: vec![
|
||||||
meta: GateMeta {
|
ModelCmdKind::Gate(Gate {
|
||||||
inputs: vec!["a".into(), "b".into(),],
|
meta: GateMeta {
|
||||||
output: "c".into(),
|
inputs: vec!["a".into(), "b".into(),],
|
||||||
external_dc: false,
|
output: "c".into(),
|
||||||
},
|
external_dc: false,
|
||||||
lut: LUT(vec![(
|
},
|
||||||
[Tristate::True, Tristate::True].into_iter().collect(),
|
lut: LUT(vec![(
|
||||||
true
|
[Tristate::True, Tristate::True].into_iter().collect(),
|
||||||
)]),
|
true
|
||||||
})],
|
)]),
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
],
|
||||||
})],
|
})],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -131,17 +140,20 @@ c
|
|||||||
outputs: None,
|
outputs: None,
|
||||||
clocks: vec![],
|
clocks: vec![],
|
||||||
},
|
},
|
||||||
commands: vec![ModelCmd::Gate(Gate {
|
commands: vec![
|
||||||
meta: GateMeta {
|
ModelCmdKind::Gate(Gate {
|
||||||
inputs: vec!["a".into(), "b".into(),],
|
meta: GateMeta {
|
||||||
output: "c".into(),
|
inputs: vec!["a".into(), "b".into(),],
|
||||||
external_dc: true,
|
output: "c".into(),
|
||||||
},
|
external_dc: true,
|
||||||
lut: LUT(vec![(
|
},
|
||||||
[Tristate::True, Tristate::True].into_iter().collect(),
|
lut: LUT(vec![(
|
||||||
true
|
[Tristate::True, Tristate::True].into_iter().collect(),
|
||||||
)]),
|
true
|
||||||
})],
|
)]),
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
],
|
||||||
})],
|
})],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -167,48 +179,51 @@ fn lut() {
|
|||||||
outputs: None,
|
outputs: None,
|
||||||
clocks: vec![],
|
clocks: vec![],
|
||||||
},
|
},
|
||||||
commands: vec![ModelCmd::Gate(Gate {
|
commands: vec![
|
||||||
meta: GateMeta {
|
ModelCmdKind::Gate(Gate {
|
||||||
inputs: vec!["v3".into(), "v6".into(), "j".into(), "u78".into()],
|
meta: GateMeta {
|
||||||
output: "v13.15".into(),
|
inputs: vec!["v3".into(), "v6".into(), "j".into(), "u78".into()],
|
||||||
external_dc: false,
|
output: "v13.15".into(),
|
||||||
},
|
external_dc: false,
|
||||||
lut: LUT(vec![
|
},
|
||||||
(
|
lut: LUT(vec![
|
||||||
[
|
(
|
||||||
Tristate::True,
|
[
|
||||||
Tristate::Ignored,
|
Tristate::True,
|
||||||
Tristate::Ignored,
|
Tristate::Ignored,
|
||||||
Tristate::False
|
Tristate::Ignored,
|
||||||
]
|
Tristate::False
|
||||||
.into_iter()
|
]
|
||||||
.collect(),
|
.into_iter()
|
||||||
true
|
.collect(),
|
||||||
),
|
true
|
||||||
(
|
),
|
||||||
[
|
(
|
||||||
Tristate::Ignored,
|
[
|
||||||
Tristate::True,
|
Tristate::Ignored,
|
||||||
Tristate::Ignored,
|
Tristate::True,
|
||||||
Tristate::True
|
Tristate::Ignored,
|
||||||
]
|
Tristate::True
|
||||||
.into_iter()
|
]
|
||||||
.collect(),
|
.into_iter()
|
||||||
true
|
.collect(),
|
||||||
),
|
true
|
||||||
(
|
),
|
||||||
[
|
(
|
||||||
Tristate::False,
|
[
|
||||||
Tristate::Ignored,
|
Tristate::False,
|
||||||
Tristate::True,
|
Tristate::Ignored,
|
||||||
Tristate::True
|
Tristate::True,
|
||||||
]
|
Tristate::True
|
||||||
.into_iter()
|
]
|
||||||
.collect(),
|
.into_iter()
|
||||||
true
|
.collect(),
|
||||||
)
|
true
|
||||||
]),
|
)
|
||||||
})],
|
]),
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
],
|
||||||
})],
|
})],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -248,15 +263,16 @@ fn submod() {
|
|||||||
clocks: vec![]
|
clocks: vec![]
|
||||||
},
|
},
|
||||||
commands: vec![
|
commands: vec![
|
||||||
ModelCmd::SubModel {
|
ModelCmdKind::SubModel {
|
||||||
name: "b".into(),
|
name: "b".into(),
|
||||||
map: vec![
|
map: vec![
|
||||||
("x".into(), "x".into()),
|
("x".into(), "x".into()),
|
||||||
("y".into(), "y".into()),
|
("y".into(), "y".into()),
|
||||||
("j".into(), "j".into())
|
("j".into(), "j".into())
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
ModelCmd::Gate(Gate {
|
.into(),
|
||||||
|
ModelCmdKind::Gate(Gate {
|
||||||
meta: GateMeta {
|
meta: GateMeta {
|
||||||
inputs: vec!["x".into()],
|
inputs: vec!["x".into()],
|
||||||
output: "j".into(),
|
output: "j".into(),
|
||||||
@@ -264,6 +280,7 @@ fn submod() {
|
|||||||
},
|
},
|
||||||
lut: LUT(vec![([Tristate::True].into_iter().collect(), true)])
|
lut: LUT(vec![([Tristate::True].into_iter().collect(), true)])
|
||||||
})
|
})
|
||||||
|
.into()
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
BlifEntry::Model(Model {
|
BlifEntry::Model(Model {
|
||||||
@@ -273,17 +290,20 @@ fn submod() {
|
|||||||
outputs: Some(vec!["j".into()]),
|
outputs: Some(vec!["j".into()]),
|
||||||
clocks: vec![]
|
clocks: vec![]
|
||||||
},
|
},
|
||||||
commands: vec![ModelCmd::Gate(Gate {
|
commands: vec![
|
||||||
meta: GateMeta {
|
ModelCmdKind::Gate(Gate {
|
||||||
inputs: vec!["x".into(), "y".into()],
|
meta: GateMeta {
|
||||||
output: "j".into(),
|
inputs: vec!["x".into(), "y".into()],
|
||||||
external_dc: false
|
output: "j".into(),
|
||||||
},
|
external_dc: false
|
||||||
lut: LUT(vec![(
|
},
|
||||||
[Tristate::True, Tristate::True].into_iter().collect(),
|
lut: LUT(vec![(
|
||||||
true
|
[Tristate::True, Tristate::True].into_iter().collect(),
|
||||||
)])
|
true
|
||||||
})]
|
)])
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
]
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@@ -434,7 +454,7 @@ fn kiss_fsm2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tech_clock_cst() {
|
fn clock_cst() {
|
||||||
let ast = parse_str_blif_to_ast(
|
let ast = parse_str_blif_to_ast(
|
||||||
"top.blif",
|
"top.blif",
|
||||||
r#"
|
r#"
|
||||||
@@ -447,3 +467,43 @@ fn tech_clock_cst() {
|
|||||||
|
|
||||||
// TODO: assert_eq
|
// TODO: assert_eq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn yosys_attrs() {
|
||||||
|
let ast = parse_str_blif_to_ast(
|
||||||
|
"top.blif",
|
||||||
|
r#"
|
||||||
|
|
||||||
|
.model MAC
|
||||||
|
.inputs clock reset io_rmii_r_RXD[0] io_rmii_r_RXD[1] io_rmii_r_RXER io_rmii_r_CRS_DV io_rmii_clk io_is10mbits io_full_duplex xmit_io_transmit xmit_io_byte[0] xmit_io_byte[1] xmit_io_byte[2] xmit_io_byte[3] xmit_io_byte[4] xmit_io_byte[5] xmit_io_byte[6] xmit_io_byte[7]
|
||||||
|
.outputs io_rmii_t_TXD[0] io_rmii_t_TXD[1] io_rmii_t_TXEN xmit_io_byte_sent recv_io_frame_start recv_io_abort_frame recv_io_valid_byte recv_io_byte[0] recv_io_byte[1] recv_io_byte[2] recv_io_byte[3] recv_io_byte[4] recv_io_byte[5] recv_io_byte[6] recv_io_byte[7] recv_io_info_carrier_lost_during_packet
|
||||||
|
.names $false
|
||||||
|
.names $true
|
||||||
|
1
|
||||||
|
.names $undef
|
||||||
|
|
||||||
|
.subckt $add A[0]=xmit_preamble_counter[0] A[1]=xmit_preamble_counter[1] A[2]=xmit_preamble_counter[2] B[0]=$true B[1]=$false B[2]=$false Y[0]=$add$build/out.v:213$277_Y[0] Y[1]=$add$build/out.v:213$277_Y[1] Y[2]=$add$build/out.v:213$277_Y[2]
|
||||||
|
.cname $add$build/out.v:213$277
|
||||||
|
.attr src "build/out.v:213.31-213.59"
|
||||||
|
.param A_SIGNED 00000000000000000000000000000000
|
||||||
|
.param A_WIDTH 00000000000000000000000000000011
|
||||||
|
.param B_SIGNED 00000000000000000000000000000000
|
||||||
|
.param B_WIDTH 00000000000000000000000000000011
|
||||||
|
.param Y_WIDTH 00000000000000000000000000000011
|
||||||
|
|
||||||
|
.subckt $and A=$not$build/out.v:170$224_Y B=$eq$build/out.v:170$225_Y Y=$and$build/out.v:170$226_Y
|
||||||
|
.cname $and$build/out.v:170$226
|
||||||
|
.attr src "build/out.v:170.31-170.103"
|
||||||
|
.param A_SIGNED 00000000000000000000000000000000
|
||||||
|
.param A_WIDTH 00000000000000000000000000000001
|
||||||
|
.param B_SIGNED 00000000000000000000000000000000
|
||||||
|
.param B_WIDTH 00000000000000000000000000000001
|
||||||
|
.param Y_WIDTH 00000000000000000000000000000001
|
||||||
|
|
||||||
|
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// TODO: assert_eq
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user