How to express a hierarchy of entities with various implementations?

I want to implement a hierarchy a bit similar to VHDL.
In VHDL a design is made up of entities, which are a specification of parameters and ports.
Each entity has several architectures which implement the functionality.
In my system, each of these architectures can also have dialects for different simulators.

So there is one type of entity, and each entity has many named architectures, each of which may support one or more languages or specific dialects.

For example, there could be an "adder" entity, with a "width" parameter, two inputs, and one output.
It has a "behavioral" architecture implemented in Verilog, which works with any Verilog simulator.
It also has a graphical "rtl" architecture that can be serialized to Verilog, VHDL, or Spice.
The graphical architecture uses other entities, such as logic gates, which also have different architectures in Verilog or Spice, including different dialects for different simulators.

You then combine this hierarchy with a configuration, which selects the architectures to use, and a simulator, which selects the dialect to use. (not all combinations are possible)

Here is a first attempt at writing something like this, but I can't quite figure out all the generics and traits. I tried to have the entity have a trait object for code architectures, and then have generic dispatch on the simulator, including traits for generic languages.

use std::collections::HashMap;

pub struct Entity {
    pub name: String,
    pub generic: HashMap<String, Parameter>,
    pub port: Vec<String>,
    pub archs: HashMap<String, Arch>, 
}

pub enum Parameter {
    Integer(i64),
    Float(f64),
    Boolean(bool),
    String(String),
}

pub enum Arch {
    Symbol(Symbol),
    Code(Box<dyn Code>), // problem
    Schematic(Schematic),
}

pub struct Symbol;
pub struct Schematic;

pub trait Code<Sim> { // attempt 1: generic trait, forces homogeneous type higher up
    fn definition(&self) -> String; // attempt 2: generic method, cannot create trait object
    fn reference(&self) -> String;
}

pub struct Architecture {
    verilog_def: String,
    verilog_ref: String,
    spice_def: String,
    spice_ref: String,
}

struct Ngspice;
struct Xyce;
struct Verilator;
struct Ickarus;

trait Spice {}
impl Spice for Ngspice {}
impl Spice for Xyce {}
trait Verilog {}
impl Verilog for Verilator {}
impl Verilog for Ickarus {}

impl Code<Ngspice> for Architecture {
    fn definition(&self) -> String { self.spice_def }
    fn reference(&self) -> String { self.spice_ref }
}

impl Code<dyn Verilog> for Architecture { // problem
    fn definition(&self) -> String { self.spice_def }
    fn reference(&self) -> String { self.spice_ref }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.