[opentitantool] Support multi-layer alias conf
We have an agreed way of connecting HyperDebug to CW310, which should be
declared in a JSON conf file, such that opentitan tool understands a
name such as A3 to be an alias of the HyperDebug native pin CN7_18.
Separately, the ChromeOS team has a particular idea of how to use the
OpenTitan chip pins, and wishes to use the name AP_FLASH_SEL as an alias
for A3. This is mostly independent of CW310 and HyperDebug, and would
apply even to future ASIC development board.
Because of the above, I foresee that we would want to simultaneously
provide a CW310/HyperDebug configuration file, and a CromeOS/EarlGrey
configuration file to OpenTitan tool.
This PR allows the --conf option to take multiple arguments, and it
adapts the alias resolution logic to be transitive.
Change-Id: I6f8a328f269dfee246a19c4d3bae9fd60f056aec
Signed-off-by: Jes B. Klinke <jbk@chromium.org>
diff --git a/sw/host/opentitanlib/src/app/mod.rs b/sw/host/opentitanlib/src/app/mod.rs
index c3109be..c0ce49b 100644
--- a/sw/host/opentitanlib/src/app/mod.rs
+++ b/sw/host/opentitanlib/src/app/mod.rs
@@ -123,10 +123,16 @@
/// string as is.
fn map_name(map: &HashMap<String, String>, name: &str) -> String {
let name = name.to_uppercase();
- // TODO(#8769): Support multi-level aliasing, either by
- // flattening after parsing all files, or by repeated lookup
- // here.
- map.get(&name).cloned().unwrap_or(name)
+ match map.get(&name) {
+ Some(v) => {
+ if v.eq(&name) {
+ name
+ } else {
+ Self::map_name(map, v)
+ }
+ }
+ None => name,
+ }
}
/// Apply given configuration to a single pins.
diff --git a/sw/host/opentitanlib/src/backend/mod.rs b/sw/host/opentitanlib/src/backend/mod.rs
index a3806f0..273e241 100644
--- a/sw/host/opentitanlib/src/backend/mod.rs
+++ b/sw/host/opentitanlib/src/backend/mod.rs
@@ -47,8 +47,8 @@
#[structopt(flatten)]
ti50emulator_opts: ti50emulator::Ti50EmulatorOpts,
- #[structopt(long, help = "Configuration files")]
- conf: Option<PathBuf>,
+ #[structopt(long, number_of_values(1), help = "Configuration files")]
+ conf: Vec<PathBuf>,
}
#[derive(Error, Debug)]
@@ -60,7 +60,7 @@
/// Creates the requested backend interface according to [`BackendOpts`].
pub fn create(args: &BackendOpts) -> Result<TransportWrapper> {
let interface = args.interface.as_str();
- let (backend, conf) = match interface {
+ let (backend, default_conf) = match interface {
"" => (create_empty_transport()?, None),
"proxy" => (proxy::create(&args.proxy_opts)?, None),
"verilator" => (
@@ -91,8 +91,14 @@
};
let mut env = TransportWrapper::new(backend);
- for conf_file in args.conf.as_ref().map(PathBuf::as_ref).or(conf) {
- process_config_file(&mut env, conf_file)?
+ if args.conf.is_empty() {
+ for conf_file in default_conf {
+ // Zero or one iteration
+ process_config_file(&mut env, conf_file)?
+ }
+ }
+ for conf_file in &args.conf {
+ process_config_file(&mut env, conf_file.as_ref())?
}
Ok(env)
}