1use jzon::{object, JsonValue};
2use std::collections::{btree_map, BTreeMap};
3
4use prjunnamed_netlist::{Const, ParamValue, Trit};
5
6#[derive(Debug)]
7pub struct SyntaxError(JsonValue);
8
9impl std::fmt::Display for SyntaxError {
10 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
11 write!(f, "syntax error near: {}", self.0)
12 }
13}
14
15impl std::error::Error for SyntaxError {}
16
17#[derive(Debug)]
18pub struct MetadataTypeError;
19
20impl std::fmt::Display for MetadataTypeError {
21 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
22 write!(f, "unexpected metadata type")
23 }
24}
25
26impl std::error::Error for MetadataTypeError {}
27
28#[derive(Debug, Clone, Copy)]
29pub enum Bit {
30 Zero,
31 One,
32 Undef,
33 HiZ,
34 Net(usize),
35}
36
37impl From<Trit> for Bit {
38 fn from(value: Trit) -> Self {
39 match value {
40 Trit::Undef => Bit::Undef,
41 Trit::Zero => Bit::Zero,
42 Trit::One => Bit::One,
43 }
44 }
45}
46
47impl TryFrom<JsonValue> for Bit {
48 type Error = SyntaxError;
49
50 fn try_from(value: JsonValue) -> Result<Self, Self::Error> {
51 match value.as_str() {
52 Some("0") => Ok(Self::Zero),
53 Some("1") => Ok(Self::One),
54 Some("x") => Ok(Self::Undef),
55 Some("z") => Ok(Self::HiZ),
56 Some(_) => Err(SyntaxError(value)),
57 None => match value.as_usize() {
58 Some(index) => Ok(Bit::Net(index)),
59 None => Err(SyntaxError(value)),
60 },
61 }
62 }
63}
64
65impl From<Bit> for JsonValue {
66 fn from(value: Bit) -> Self {
67 match value {
68 Bit::Zero => "0".into(),
69 Bit::One => "1".into(),
70 Bit::Undef => "x".into(),
71 Bit::HiZ => "z".into(),
72 Bit::Net(index) => index.into(),
73 }
74 }
75}
76
77#[derive(Debug, Clone)]
78pub struct BitVector(pub Vec<Bit>);
79
80impl BitVector {
81 pub fn iter(&self) -> std::slice::Iter<'_, Bit> {
82 self.0.iter()
83 }
84
85 pub fn len(&self) -> usize {
86 self.0.len()
87 }
88
89 pub fn concat(&self, other: &BitVector) -> Self {
90 let mut bits = self.0.clone();
91 bits.extend(&other.0);
92 BitVector(bits)
93 }
94}
95
96impl From<Bit> for BitVector {
97 fn from(value: Bit) -> Self {
98 BitVector(vec![value])
99 }
100}
101
102impl From<Const> for BitVector {
103 fn from(value: Const) -> Self {
104 BitVector(value.iter().map(Into::into).collect::<Vec<_>>())
105 }
106}
107
108impl TryFrom<JsonValue> for BitVector {
109 type Error = SyntaxError;
110
111 fn try_from(mut value: JsonValue) -> Result<Self, Self::Error> {
112 if value.is_array() {
113 let mut bits = vec![];
114 for bit_value in value.members_mut() {
115 bits.push(Bit::try_from(bit_value.take())?);
116 }
117 Ok(BitVector(bits))
118 } else {
119 Err(SyntaxError(value))
120 }
121 }
122}
123
124impl From<BitVector> for JsonValue {
125 fn from(value: BitVector) -> JsonValue {
126 JsonValue::Array(value.0.iter().copied().map(JsonValue::from).collect::<Vec<_>>())
127 }
128}
129
130#[derive(Debug, Clone)]
131pub enum MetadataValue {
132 String(String),
133 Const(Const),
134}
135
136impl MetadataValue {
137 pub fn as_const(&self) -> Result<Const, MetadataTypeError> {
138 match self {
139 Self::Const(value) => Ok(value.clone()),
140 _ => Err(MetadataTypeError),
141 }
142 }
143
144 pub fn as_i32(&self) -> Result<i32, MetadataTypeError> {
145 match self {
146 Self::Const(value) if value.len() == 32 => {
147 let mut i32_value = 0;
148 for (index, trit) in value.iter().enumerate() {
149 match trit {
150 Trit::One => i32_value |= 1 << index,
151 Trit::Zero => (),
152 Trit::Undef => return Err(MetadataTypeError),
153 }
154 }
155 Ok(i32_value)
156 }
157 _ => Err(MetadataTypeError),
158 }
159 }
160
161 pub fn as_bool(&self) -> Result<bool, MetadataTypeError> {
162 match self {
163 Self::Const(value) => match value.try_into() {
164 Ok(0u64) => Ok(false),
165 Ok(1u64) => Ok(true),
166 _ => Err(MetadataTypeError),
167 },
168 _ => Err(MetadataTypeError),
169 }
170 }
171}
172
173impl From<Const> for MetadataValue {
174 fn from(value: Const) -> Self {
175 MetadataValue::Const(value)
176 }
177}
178
179macro_rules! metadata_value_from_integral {
180 ($int:ty) => {
181 impl From<$int> for MetadataValue {
182 fn from(value: $int) -> Self {
183 let mut trits = vec![];
184 for index in 0..<$int>::BITS {
185 trits.push(if value & (1 << index) != 0 { Trit::One } else { Trit::Zero });
186 }
187 MetadataValue::Const(trits.into())
188 }
189 }
190 };
191}
192
193metadata_value_from_integral!(u64);
194metadata_value_from_integral!(i64);
195metadata_value_from_integral!(u32);
196metadata_value_from_integral!(i32);
197
198impl From<usize> for MetadataValue {
199 fn from(value: usize) -> Self {
200 (value as i32).into()
201 }
202}
203
204impl From<bool> for MetadataValue {
205 fn from(value: bool) -> Self {
206 if value { 1i32 } else { 0 }.into()
207 }
208}
209
210impl From<String> for MetadataValue {
211 fn from(value: String) -> Self {
212 MetadataValue::String(value)
213 }
214}
215
216impl From<&String> for MetadataValue {
217 fn from(value: &String) -> Self {
218 MetadataValue::String(value.to_owned())
219 }
220}
221
222impl From<&str> for MetadataValue {
223 fn from(value: &str) -> Self {
224 MetadataValue::String(value.to_owned())
225 }
226}
227
228impl From<ParamValue> for MetadataValue {
229 fn from(value: ParamValue) -> Self {
230 match value {
231 ParamValue::Const(value) => value.into(),
232 ParamValue::Int(value) => value.into(),
233 ParamValue::String(value) => value.into(),
234 ParamValue::Float(_) => {
235 unimplemented!("Yosys JSON does not define serialization for floating point parameters")
236 }
237 }
238 }
239}
240
241impl From<&ParamValue> for MetadataValue {
242 fn from(value: &ParamValue) -> Self {
243 value.clone().into()
244 }
245}
246
247enum MetadataValueClass {
248 Bits,
249 BitsAndSpaces,
250 Other,
251}
252
253impl MetadataValueClass {
254 fn compute(value: &str) -> MetadataValueClass {
255 let mut class = MetadataValueClass::Bits;
256 for char in value.chars() {
257 match (&class, char) {
258 (MetadataValueClass::Bits, '0' | '1' | 'x' | 'z') => (),
259 (MetadataValueClass::BitsAndSpaces, ' ') => (),
260 (MetadataValueClass::Bits, ' ') => class = MetadataValueClass::BitsAndSpaces,
261 _ => class = MetadataValueClass::Other,
262 }
263 }
264 class
265 }
266}
267
268impl TryFrom<JsonValue> for MetadataValue {
269 type Error = SyntaxError;
270
271 fn try_from(value: JsonValue) -> Result<Self, Self::Error> {
272 if let Some(value) = value.as_str() {
273 Ok(match MetadataValueClass::compute(value) {
274 MetadataValueClass::Bits => MetadataValue::Const(
275 value
276 .chars()
277 .rev()
278 .map(|char| match char {
279 'x' => Trit::Undef,
280 '0' => Trit::Zero,
281 '1' => Trit::One,
282 _ => unreachable!(),
283 })
284 .collect::<Vec<_>>()
285 .into(),
286 ),
287 MetadataValueClass::BitsAndSpaces => MetadataValue::String(value.strip_suffix(" ").unwrap().to_owned()),
288 MetadataValueClass::Other => MetadataValue::String(value.to_owned()),
289 })
290 } else {
291 Err(SyntaxError(value))
292 }
293 }
294}
295
296impl From<MetadataValue> for JsonValue {
297 fn from(value: MetadataValue) -> JsonValue {
298 match value {
299 MetadataValue::String(value) => match MetadataValueClass::compute(&value) {
300 MetadataValueClass::Bits => value.into(),
301 MetadataValueClass::BitsAndSpaces => (value + " ").into(),
302 MetadataValueClass::Other => value.into(),
303 },
304 MetadataValue::Const(value) => value
305 .iter()
306 .rev()
307 .map(|trit| match trit {
308 Trit::Undef => "x",
309 Trit::Zero => "0",
310 Trit::One => "1",
311 })
312 .collect::<String>()
313 .into(),
314 }
315 }
316}
317
318#[derive(Debug)]
319pub struct Metadata(pub BTreeMap<String, MetadataValue>);
320
321impl Metadata {
322 pub fn new() -> Metadata {
323 Metadata(BTreeMap::new())
324 }
325
326 pub fn iter(&self) -> btree_map::Iter<'_, String, MetadataValue> {
327 self.0.iter()
328 }
329
330 pub fn get(&self, key: &str) -> Option<&MetadataValue> {
331 self.0.get(key)
332 }
333
334 pub fn add(&mut self, key: &str, value: impl ToOwned<Owned = MetadataValue>) {
335 self.0.insert(key.to_owned(), value.to_owned());
336 }
337
338 pub fn extend(&mut self, values: impl IntoIterator<Item = (String, MetadataValue)>) {
339 self.0.extend(values);
340 }
341}
342
343impl TryFrom<JsonValue> for Metadata {
344 type Error = SyntaxError;
345
346 fn try_from(mut value: JsonValue) -> Result<Self, Self::Error> {
347 if value.is_object() {
348 let mut entries = BTreeMap::new();
349 for (name, value) in value.entries_mut() {
350 entries.insert(name.to_owned(), value.take().try_into()?);
351 }
352 Ok(Metadata(entries))
353 } else {
354 Err(SyntaxError(value))
355 }
356 }
357}
358
359impl From<Metadata> for JsonValue {
360 fn from(value: Metadata) -> JsonValue {
361 value.0.into()
362 }
363}
364
365#[derive(Debug)]
366pub struct Map<V>(pub BTreeMap<String, V>);
367
368impl<V> Map<V> {
369 pub fn new() -> Map<V> {
370 Map(BTreeMap::new())
371 }
372
373 pub fn iter(&self) -> btree_map::Iter<'_, String, V> {
374 self.0.iter()
375 }
376
377 pub fn get(&self, key: &str) -> Option<&V> {
378 self.0.get(key)
379 }
380
381 pub fn contains_key(&self, key: &str) -> bool {
382 self.0.contains_key(key)
383 }
384
385 pub fn add(&mut self, key: &str, value: V) {
386 self.0.insert(key.to_owned(), value);
387 }
388}
389
390impl<V> From<BTreeMap<String, V>> for Map<V> {
391 fn from(value: BTreeMap<String, V>) -> Self {
392 Map(value)
393 }
394}
395
396impl<V: TryFrom<JsonValue, Error = SyntaxError>> TryFrom<JsonValue> for Map<V> {
397 type Error = SyntaxError;
398
399 fn try_from(mut value: JsonValue) -> Result<Self, Self::Error> {
400 if value.is_object() {
401 let mut entries = BTreeMap::new();
402 for (name, value) in value.entries_mut() {
403 entries.insert(name.to_owned(), value.take().try_into()?);
404 }
405 Ok(Map(entries))
406 } else {
407 Err(SyntaxError(value))
408 }
409 }
410}
411
412impl<V: Into<JsonValue>> From<Map<V>> for JsonValue {
413 fn from(value: Map<V>) -> JsonValue {
414 value.0.into()
415 }
416}
417
418#[derive(Debug, Clone, Copy, PartialEq, Eq)]
419pub enum PortDirection {
420 Input,
421 Output,
422 Inout,
423}
424
425impl TryFrom<JsonValue> for PortDirection {
426 type Error = SyntaxError;
427
428 fn try_from(value: JsonValue) -> Result<Self, Self::Error> {
429 match value.as_str() {
430 Some("input") => Ok(PortDirection::Input),
431 Some("output") => Ok(PortDirection::Output),
432 Some("inout") => Ok(PortDirection::Inout),
433 _ => Err(SyntaxError(value)),
434 }
435 }
436}
437
438impl From<PortDirection> for JsonValue {
439 fn from(value: PortDirection) -> JsonValue {
440 match value {
441 PortDirection::Input => "input".into(),
442 PortDirection::Output => "output".into(),
443 PortDirection::Inout => "inout".into(),
444 }
445 }
446}
447
448#[derive(Debug)]
449pub struct PortDetails {
450 pub direction: PortDirection,
451 pub bits: BitVector,
452 pub offset: usize,
453 pub upto: bool,
454 pub signed: bool,
455}
456
457impl PortDetails {
458 pub fn new(direction: PortDirection, bits: BitVector) -> PortDetails {
459 PortDetails { direction, bits, offset: 0, upto: false, signed: false }
460 }
461}
462
463impl TryFrom<JsonValue> for PortDetails {
464 type Error = SyntaxError;
465
466 fn try_from(mut value: JsonValue) -> Result<Self, Self::Error> {
467 let direction = PortDirection::try_from(value["direction"].take())?;
468 let bits = BitVector::try_from(value["bits"].take())?;
469 let offset = value["offset"].as_usize().unwrap_or(0);
470 let upto = value["upto"].as_usize().unwrap_or(0) != 0;
471 let signed = value["signed"].as_usize().unwrap_or(0) != 0;
472 Ok(PortDetails { direction, bits, offset, upto, signed })
473 }
474}
475
476impl From<PortDetails> for JsonValue {
477 fn from(value: PortDetails) -> JsonValue {
478 let mut json = object! {
479 direction: value.direction,
480 bits: value.bits,
481 };
482 if value.offset != 0 {
483 json["offset"] = value.offset.into();
484 }
485 if value.upto {
486 json["upto"] = 1.into();
487 }
488 if value.signed {
489 json["signed"] = 1.into();
490 }
491 json
492 }
493}
494
495#[derive(Debug)]
496pub struct CellDetails {
497 pub hide_name: bool,
498 pub type_: String,
499 pub parameters: Metadata,
500 pub attributes: Metadata,
501 pub port_directions: Map<PortDirection>,
502 pub connections: Map<BitVector>,
503}
504
505impl CellDetails {
506 pub fn new(type_: &str) -> CellDetails {
507 CellDetails {
508 hide_name: false,
509 type_: type_.into(),
510 parameters: Metadata::new(),
511 attributes: Metadata::new(),
512 port_directions: Map::new(),
513 connections: Map::new(),
514 }
515 }
516
517 pub fn attr(mut self, name: &str, value: impl Into<MetadataValue>) -> CellDetails {
518 self.attributes.add(name, value.into());
519 self
520 }
521
522 pub fn attrs(mut self, attrs: impl IntoIterator<Item = (String, MetadataValue)>) -> CellDetails {
523 self.attributes.extend(attrs);
524 self
525 }
526
527 pub fn param(mut self, name: &str, value: impl Into<MetadataValue>) -> CellDetails {
528 self.parameters.add(name, value.into());
529 self
530 }
531
532 pub fn port(mut self, name: &str, port_direction: PortDirection, connection: impl Into<BitVector>) -> CellDetails {
533 self.port_directions.add(name, port_direction);
534 self.connections.add(name, connection.into());
535 self
536 }
537
538 pub fn input(self, name: &str, connection: impl Into<BitVector>) -> CellDetails {
539 self.port(name, PortDirection::Input, connection)
540 }
541
542 pub fn output(self, name: &str, connection: impl Into<BitVector>) -> CellDetails {
543 self.port(name, PortDirection::Output, connection)
544 }
545
546 pub fn inout(self, name: &str, connection: impl Into<BitVector>) -> CellDetails {
547 self.port(name, PortDirection::Inout, connection)
548 }
549
550 pub fn add_to(mut self, name: &str, module: &mut Module) {
551 let mut name = name;
552 let hdlname: String;
553 if let Some(MetadataValue::String(value)) = self.attributes.0.get("hdlname") {
554 hdlname = value.replace(' ', ".");
555 if !module.cells.contains_key(value) {
556 name = &hdlname;
557 }
558 }
559 assert!(!module.cells.contains_key(name));
560 self.hide_name = name.starts_with('$');
561 module.cells.add(name, self)
562 }
563}
564
565impl TryFrom<JsonValue> for CellDetails {
566 type Error = SyntaxError;
567
568 fn try_from(mut value: JsonValue) -> Result<Self, Self::Error> {
569 let hide_name = value["hide_name"].as_usize().unwrap_or(0) != 0;
570 let type_ = value["type"].as_str().map(|s| s.to_owned()).ok_or(SyntaxError(value["type"].take()))?;
571 let parameters = Metadata::try_from(value["parameters"].take())?;
572 let attributes = Metadata::try_from(value["attributes"].take())?;
573 let port_directions = Map::<PortDirection>::try_from(value["port_directions"].take())?;
574 let connections = Map::<BitVector>::try_from(value["connections"].take())?;
575 Ok(CellDetails { hide_name, type_, parameters, attributes, port_directions, connections })
576 }
577}
578
579impl From<CellDetails> for JsonValue {
580 fn from(value: CellDetails) -> JsonValue {
581 object! {
582 hide_name: if value.hide_name { 1 } else { 0 },
583 type: value.type_,
584 parameters: value.parameters,
585 attributes: value.attributes,
586 port_directions: value.port_directions,
587 connections: value.connections,
588 }
589 }
590}
591
592#[derive(Debug)]
593pub struct MemoryDetails {
594 pub hide_name: bool,
595 pub attributes: Metadata,
596 pub width: usize,
597 pub start_offset: usize,
598 pub size: usize,
599}
600
601impl TryFrom<JsonValue> for MemoryDetails {
602 type Error = SyntaxError;
603
604 fn try_from(mut value: JsonValue) -> Result<Self, Self::Error> {
605 let hide_name = value["hide_name"].as_usize().unwrap_or(0) != 0;
606 let attributes = Metadata::try_from(value["attributes"].take())?;
607 let width = value["width"].as_usize().ok_or(SyntaxError(value["width"].take()))?;
608 let start_offset = value["start_offset"].as_usize().ok_or(SyntaxError(value["start_offset"].take()))?;
609 let size = value["size"].as_usize().ok_or(SyntaxError(value["size"].take()))?;
610 Ok(MemoryDetails { hide_name, attributes, width, start_offset, size })
611 }
612}
613
614impl From<MemoryDetails> for JsonValue {
615 fn from(value: MemoryDetails) -> JsonValue {
616 object! {
617 hide_name: if value.hide_name { 1 } else { 0 },
618 attributes: value.attributes,
619 width: value.width,
620 start_offset: value.start_offset,
621 size: value.size,
622 }
623 }
624}
625
626#[derive(Debug)]
627pub struct NetDetails {
628 pub hide_name: bool,
629 pub attributes: Metadata,
630 pub bits: BitVector,
631 pub offset: usize,
632 pub upto: bool,
633 pub signed: bool,
634}
635
636impl NetDetails {
637 pub fn new(bits: impl Into<BitVector>) -> NetDetails {
638 NetDetails {
639 hide_name: false,
640 attributes: Metadata::new(),
641 bits: bits.into(),
642 offset: 0,
643 upto: false,
644 signed: false,
645 }
646 }
647
648 pub fn attr(mut self, name: &str, value: impl Into<MetadataValue>) -> NetDetails {
649 self.attributes.add(name, value.into());
650 self
651 }
652
653 pub fn attrs(mut self, attrs: impl IntoIterator<Item = (String, MetadataValue)>) -> NetDetails {
654 self.attributes.extend(attrs);
655 self
656 }
657
658 pub fn add_to(mut self, name: &str, module: &mut Module) {
659 assert!(!module.netnames.contains_key(name));
660 self.hide_name = name.starts_with('$');
661 module.netnames.add(name, self)
662 }
663}
664
665impl TryFrom<JsonValue> for NetDetails {
666 type Error = SyntaxError;
667
668 fn try_from(mut value: JsonValue) -> Result<Self, Self::Error> {
669 let hide_name = value["hide_name"].as_usize().unwrap_or(0) != 0;
670 let attributes = Metadata::try_from(value["attributes"].take())?;
671 let bits = BitVector::try_from(value["bits"].take())?;
672 let offset = value["offset"].as_usize().unwrap_or(0);
673 let upto = value["upto"].as_usize().unwrap_or(0) != 0;
674 let signed = value["signed"].as_usize().unwrap_or(0) != 0;
675 Ok(NetDetails { hide_name, attributes, bits, offset, upto, signed })
676 }
677}
678
679impl From<NetDetails> for JsonValue {
680 fn from(value: NetDetails) -> JsonValue {
681 let mut json = object! {
682 hide_name: if value.hide_name { 1 } else { 0 },
683 attributes: value.attributes,
684 bits: value.bits,
685 };
686 if value.offset != 0 {
687 json["offset"] = value.offset.into();
688 }
689 if value.upto {
690 json["upto"] = 1.into();
691 }
692 if value.signed {
693 json["signed"] = 1.into();
694 }
695 json
696 }
697}
698
699#[derive(Debug)]
700pub struct Module {
701 pub attributes: Metadata,
702 pub parameter_default_values: Metadata,
703 pub ports: Map<PortDetails>,
704 pub cells: Map<CellDetails>,
705 pub memories: Map<MemoryDetails>,
706 pub netnames: Map<NetDetails>,
707}
708
709impl Module {
710 pub fn new() -> Module {
711 Module {
712 attributes: Metadata::new(),
713 parameter_default_values: Metadata::new(),
714 ports: Map::new(),
715 cells: Map::new(),
716 memories: Map::new(),
717 netnames: Map::new(),
718 }
719 }
720}
721
722impl TryFrom<JsonValue> for Module {
723 type Error = SyntaxError;
724
725 fn try_from(mut value: JsonValue) -> Result<Self, Self::Error> {
726 let attributes = Metadata::try_from(value["attributes"].take())?;
727 let parameter_default_values = if value.has_key("parameter_default_values") {
728 Metadata::try_from(value["parameter_default_values"].take())?
729 } else {
730 Metadata::new()
731 };
732 let ports = Map::<PortDetails>::try_from(value["ports"].take())?;
733 let cells = Map::<CellDetails>::try_from(value["cells"].take())?;
734 let memories = if value.has_key("memories") {
735 Map::<MemoryDetails>::try_from(value["memories"].take())?
736 } else {
737 Map::new()
738 };
739 let netnames = Map::<NetDetails>::try_from(value["netnames"].take())?;
740 Ok(Module { attributes, parameter_default_values, ports, cells, memories, netnames })
741 }
742}
743
744impl From<Module> for JsonValue {
745 fn from(value: Module) -> JsonValue {
746 object! {
747 attributes: value.attributes,
748 parameter_default_values: value.parameter_default_values,
749 ports: value.ports,
750 cells: value.cells,
751 memories: value.memories,
752 netnames: value.netnames,
753 }
754 }
755}
756
757#[derive(Debug)]
759pub struct Design {
760 pub creator: String,
761 pub modules: Map<Module>,
762 }
764
765impl TryFrom<JsonValue> for Design {
766 type Error = SyntaxError;
767
768 fn try_from(mut value: JsonValue) -> Result<Self, Self::Error> {
769 let creator = value["creator"].as_str().map(|s| s.to_owned()).ok_or(SyntaxError(value["creator"].take()))?;
770 let modules = Map::<Module>::try_from(value["modules"].take())?;
771 Ok(Design { creator, modules })
772 }
773}
774
775impl From<Design> for JsonValue {
776 fn from(value: Design) -> JsonValue {
777 object! {
778 creator: value.creator,
779 modules: value.modules,
780 }
781 }
782}